ś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.

Brak komentarzy:

Prześlij komentarz