Pokazywanie postów oznaczonych etykietą logical. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą logical. Pokaż wszystkie posty

czwartek, 23 sierpnia 2012

[WPF] Logical Resources

Zasobem logicznym może być np. kolor, brush czy czcionka. Mamy do dyspozycji dwa rodzaje zasobów logicznych.

StaticResource -statyczne, ładowane w momencie uruchamiania aplikacji, nie podlegają zmianom w czasie trwania aplikacji, ale też nie wymagają dodatkowych zasobów do śledzenia zmian.

DynamicResource - mogą być zmieniane wielokrotnie w czasie trwania aplikacji, ładowane są dopiero w momencie, kiedy zachodzi taka potrzeba, np. przy wejściu do danej strony.

Na poziomie okna zasoby definiowane są w następujący sposób :

    <Window.Resources>
        <SolidColorBrush x:Key="myBrush" Color="Azure" />
    </Window.Resources>

Mogą być także definiowane na innych poziomach, np. w pliku App.xaml jako zasoby globalne dla całej aplikacji.

   <Application.Resources>
        <ResourceDictionary>
            <SolidColorBrush x:Key="globalBrush" Color="DarkOliveGreen" />
        </ResourceDictionary>
    </Application.Resources>

Do zasobów odwołujemy się w następujący sposób:

<Rectangle Fill="{StaticResource myBrush}" Name="rectangle1" Stroke="Black" VerticalAlignment="Top" Width="491" />
<Rectangle Fill="{DynamicResource globalBrush}"  Name="rectangle2" Stroke="Black" VerticalAlignment="Top" Width="491" />
   

Istnieje możliwość używania tych samych kluczy na różnych poziomach. Podczas wczytywania zasobu, przeszukiwane jest drzewo wizualne, od najbardziej lokalnego poziomu. Jeśli zostanie znaleziony zasób na poziomie okna, to jest on ładowany, jeśli nie, to sprawdzany jest poziom aplikacji, później zasoby systemowe, a gdy również tam nie zostanie nic znalezione, rzucany jest wyjątek.

Warto także pamiętać o tym, że domyślnie, gdy zdefiniujemy zasób i odwołamy się do niego w wielu miejscach, to używana jest jedna instancja. Możemy wymusić tworzenie nowego zasobu poprzez ustawiania atrybutu x:Shared=”False”.

Zasoby można także definiować oraz przydzielać z poziomu Code Behind.


 private void rectangle2_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Resources.Add("addedResource", new SolidColorBrush(Colors.Khaki));
            App.Current.Resources.Add("newResource", new SolidColorBrush(Colors.Honeydew));
        }

        private void rectangle1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            ((Rectangle)sender).Fill = (SolidColorBrush)Resources["addedResource"];
            ((Rectangle)sender).Stroke = (SolidColorBrush)App.Current.Resources["newResource"];
        }

środa, 15 sierpnia 2012

[WPF] Logical Tree, Visual Tree

Dużą zaletą technologii WPF jest oddzielenie wyglądu od zachowania. Wygląd zapisujemy w plikach xaml, natomiast zachowanie w plikach C#. Może się tak zdarzyć, że z poziomu kodu będziemy chcieli modyfikować pewne własności kontrolek. W tym miejscu z pomocą przychodzą dwa terminy wprowadzane przez WPF : drzewo wizualne oraz drzewo logiczne. Drzewo logiczne, to układ strukturalny kontrolek w naszym widoku, tak, jak zdefinowane są w xaml. Do przeszukiwania tego drzewa służy klasa LogicalTreeHelper. Drzewo wizualne zawiera dodatkowe właściwości, takie jak zawartość poszczególnych kontrolek. Na poniższym przykładzie można zobaczyć, jakie właściwości są dostępne w drzewie wizualnym za pomocą klasy VisualTreeHelper.

Zbudowane zostało proste okno z kilkoma poziomami zagnieżdżenia kontrolek i trzema radiobuttonami, gdzie każdy ma ustawiony inny poziom widoczności. Do wypisywania drzewa zastosowano metody przedstawione w książce Adama Nathana, WPF Unleashed.

<Window x:Class="VisualTreeHelper_LogicalTreeHelper.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid x:Name="RootGrid">
        <StackPanel>
            <Grid Width="200" Height="100">
                <Button Content="Button1" Margin="30,30,46.5,31.5" />
                <CheckBox Content="Checkbox1" />
            </Grid>
            <Grid Width="200" Height="100">
             <ListBox Margin="21.5,8,26.5,30" RenderTransformOrigin="0.507,0.355" Background="#FFD24848">
              <ListBoxItem/>
             </ListBox>
                <RadioButton x:Name="rb_Visible" Content="RadioButton" Height="18.5"  Visibility="Visible"/>
                <RadioButton x:Name="rb_Hidden" Content="RadioButton" Height="18.5"  Visibility="Hidden"/>
             <RadioButton x:Name="rb_Collapsed" Content="RadioButton" Visibility="Collapsed"/>

            </Grid>
        </StackPanel>
    </Grid>
</Window>


 public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        protected override void OnContentRendered(EventArgs e)
        {
            base.OnContentRendered(e);
            Debug.WriteLine("Logical Tree");
            PrintLogicalTree(0, this);
            Debug.WriteLine("Visual Tree");
            PrintVisualTree(0, this);
        }

        public void PrintLogicalTree(int depth, object obj)
        {
            Debug.WriteLine(new string(' ', depth) + obj);

            if(obj as DependencyObject == null)
                return;

            foreach (object child in LogicalTreeHelper.GetChildren(obj as DependencyObject))
            {
                PrintLogicalTree(depth + 1, child);
            }
        }

        public void PrintVisualTree(int depth, DependencyObject obj)
        {
            Debug.WriteLine(new string(' ', depth) + obj)
            ;
            // Recursive call for each visual child
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
                PrintVisualTree(depth + 1, VisualTreeHelper.GetChild(obj, i));
        }

    }

Po uruchomieniu programu output przedstawiał się następująco :

Logical Tree
VisualTreeHelper_LogicalTreeHelper.MainWindow
 System.Windows.Controls.Grid
  System.Windows.Controls.StackPanel
   System.Windows.Controls.Grid
    System.Windows.Controls.Button: Button1
     Button1
    System.Windows.Controls.CheckBox Content:Checkbox1 IsChecked:False
     Checkbox1
   System.Windows.Controls.Grid
    System.Windows.Controls.ListBox Items.Count:1
     System.Windows.Controls.ListBoxItem
    System.Windows.Controls.RadioButton Content:RadioButton IsChecked:False
     RadioButton
    System.Windows.Controls.RadioButton Content:RadioButton IsChecked:False
     RadioButton
    System.Windows.Controls.RadioButton Content:RadioButton IsChecked:False
     RadioButton
Visual Tree
VisualTreeHelper_LogicalTreeHelper.MainWindow
 System.Windows.Controls.Border
  System.Windows.Documents.AdornerDecorator
   System.Windows.Controls.ContentPresenter
    System.Windows.Controls.Grid
     System.Windows.Controls.StackPanel
      System.Windows.Controls.Grid
       System.Windows.Controls.Button: Button1
        Microsoft.Windows.Themes.ButtonChrome
         System.Windows.Controls.ContentPresenter
          System.Windows.Controls.TextBlock
       System.Windows.Controls.CheckBox Content:Checkbox1 IsChecked:False
        System.Windows.Controls.Primitives.BulletDecorator
         Microsoft.Windows.Themes.BulletChrome
         System.Windows.Controls.ContentPresenter
          System.Windows.Controls.TextBlock
      System.Windows.Controls.Grid
       System.Windows.Controls.ListBox Items.Count:1
        System.Windows.Controls.Border
         System.Windows.Controls.ScrollViewer
          System.Windows.Controls.Grid
           System.Windows.Shapes.Rectangle
           System.Windows.Controls.ScrollContentPresenter
            System.Windows.Controls.ItemsPresenter
             System.Windows.Controls.VirtualizingStackPanel
              System.Windows.Controls.ListBoxItem
               System.Windows.Controls.Border
                System.Windows.Controls.ContentPresenter
            System.Windows.Documents.AdornerLayer
           System.Windows.Controls.Primitives.ScrollBar Minimum:0 Maximum:0 Value:0
           System.Windows.Controls.Primitives.ScrollBar Minimum:0 Maximum:0 Value:0
       System.Windows.Controls.RadioButton Content:RadioButton IsChecked:False
        System.Windows.Controls.Primitives.BulletDecorator
         Microsoft.Windows.Themes.BulletChrome
         System.Windows.Controls.ContentPresenter
          System.Windows.Controls.TextBlock
       System.Windows.Controls.RadioButton Content:RadioButton IsChecked:False
        System.Windows.Controls.Primitives.BulletDecorator
         Microsoft.Windows.Themes.BulletChrome
         System.Windows.Controls.ContentPresenter
          System.Windows.Controls.TextBlock
       System.Windows.Controls.RadioButton Content:RadioButton IsChecked:False
   System.Windows.Documents.AdornerLayer

Warto zwrócić uwagę na fakt, iż dla radiobuttona z visibility ustawionym na collapsed cała zawartość została usunięta z drzewa wizualnego.Poza tym, dla każdej kontrolki wyświetlana jest każda wyrenderowana składowa, taka jak ramka, czy tekst w przycisku.