WPF 에서는
Logical Tree 와 Visual Tree 가 있다.
자세한 개념은 MSDN 이 가장 잘 설명해 놓았다.
(http://msdn.microsoft.com/ko-kr/library/ms753391.aspx)
쉽게 이야기 하면
어떤 "UI요소" 가 구성된 하위의 구조를 이야기 한다.
하나의 UI요소 는 다른 여러 UI요소들로 구성되어 있고
UI요소의 Template 안에는 이 UI요소 를 표현하는 여러 UI요소 가 들어있다.
TextBox 가 하나 있다면
<TextBox />
TextBox 의 Template 에는 여러 UI요소들이 TextBox 의 모양을 구성하고 있다.
<ControlTemplate x:Key="TextBoxBaseControlTemplate1" TargetType="{x:Type TextBoxBase}">
<Themes:ListBoxChrome x:Name="Bd"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
RenderMouseOver="{TemplateBinding IsMouseOver}"
RenderFocused="{TemplateBinding IsKeyboardFocusWithin}" SnapsToDevicePixels="True">
<ScrollViewer x:Name="PART_ContentHost"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Themes:ListBoxChrome>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" TargetName="Bd"
Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
<Setter Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
Template 은 WPF 의 가장 기본적인 내용이다.
이런 윈도우를 구성해보았다.
<Window x:Class="SampleLogicalTree.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:My="clr-namespace:SampleLogicalTree"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Button Grid.Row="0" Content="Button 1" Click="OnButtonClick"/>
<Grid Grid.Row="1" Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Content="Button 2-1" />
<Button Grid.Column="1" Content="Button 2-2" />
<Button Grid.Column="2" Content="Button 2-3" />
</Grid>
<Button Grid.Row="2" Content="Button 3" />
</Grid>
</Window>
이런 윈도우에 포함된 UI요소들을 트리로 나열한 것이 Logical Tree 이다.
<SampleLogicalTree.MainWindow>
<System.Windows.Controls.Grid>
<System.Windows.Controls.Button />
<System.Windows.Controls.Grid>
<System.Windows.Controls.Button />
<System.Windows.Controls.Button />
<System.Windows.Controls.Button />
</System.Windows.Controls.Grid>
<System.Windows.Controls.Button />
</System.Windows.Controls.Grid>
</SampleLogicalTree.MainWindow>
그리고 각각의 UI요소 들이 그 안에 시각적인 표현을 위해서 구성된 하위 UI요소 까지 트리로 나열한 것이 Visual Tree 이다
<SampleLogicalTree.MainWindow>
<System.Windows.Controls.Border>
<System.Windows.Documents.AdornerDecorator>
<System.Windows.Controls.ContentPresenter>
<System.Windows.Controls.Grid>
<System.Windows.Controls.Button>
<Microsoft.Windows.Themes.ButtonChrome>
<System.Windows.Controls.ContentPresenter>
<System.Windows.Controls.TextBlock />
</System.Windows.Controls.ContentPresenter>
</Microsoft.Windows.Themes.ButtonChrome>
</System.Windows.Controls.Button>
<System.Windows.Controls.Grid>
<System.Windows.Controls.Button>
<Microsoft.Windows.Themes.ButtonChrome>
<System.Windows.Controls.ContentPresenter>
<System.Windows.Controls.TextBlock />
</System.Windows.Controls.ContentPresenter>
</Microsoft.Windows.Themes.ButtonChrome>
</System.Windows.Controls.Button>
<System.Windows.Controls.Button>
<Microsoft.Windows.Themes.ButtonChrome>
<System.Windows.Controls.ContentPresenter>
<System.Windows.Controls.TextBlock />
</System.Windows.Controls.ContentPresenter>
</Microsoft.Windows.Themes.ButtonChrome>
</System.Windows.Controls.Button>
<System.Windows.Controls.Button>
<Microsoft.Windows.Themes.ButtonChrome>
<System.Windows.Controls.ContentPresenter>
<System.Windows.Controls.TextBlock />
</System.Windows.Controls.ContentPresenter>
</Microsoft.Windows.Themes.ButtonChrome>
</System.Windows.Controls.Button>
</System.Windows.Controls.Grid>
<System.Windows.Controls.Button>
<Microsoft.Windows.Themes.ButtonChrome>
<System.Windows.Controls.ContentPresenter>
<System.Windows.Controls.TextBlock />
</System.Windows.Controls.ContentPresenter>
</Microsoft.Windows.Themes.ButtonChrome>
</System.Windows.Controls.Button>
</System.Windows.Controls.Grid>
</System.Windows.Controls.ContentPresenter>
<System.Windows.Documents.AdornerLayer />
</System.Windows.Documents.AdornerDecorator>
</System.Windows.Controls.Border>
</SampleLogicalTree.MainWindow>
WPF 에서는 당연히 Logical Tree 와 Visual Tree 를 만들 수 있는 방법을 제공한다.
Logical Tree 를 가져올 수 있는 "LogicalTreeHelper" 와
System.Windows.LogicalTreeHelper
System.IO.File.WriteAllText(@"C:\\LogicalTree.TXT", GetLogicalTree(this/*대상 UI요소*/).ToString());
public XElement GetLogicalTree(Object obj)
{
XElement myEl = null;
if (obj is FrameworkElement)
{
FrameworkElement element = (FrameworkElement)obj;
myEl = new XElement(element.GetType().ToString());
System.Collections.IEnumerable children = System.Windows.LogicalTreeHelper.GetChildren(element);
foreach (Object child in children)
{
XElement childTree = GetLogicalTree(child);
if (childTree != null)
myEl.Add(childTree);
}
}
return myEl;
}
Visual Tree 를 가져올 수 있는 "VisualTreeHelper" 를
System.Windows.Media.VisualTreeHelper
System.IO.File.WriteAllText(@"C:\\VisualTree.TXT", GetVisualTree(this/*대상 UI요소*/).ToString());
public XElement GetVisualTree(Object obj)
{
XElement myEl = null;
if (obj is FrameworkElement)
{
FrameworkElement element = (FrameworkElement)obj;
myEl = new XElement(element.GetType().ToString());
for(int i = 0; i < System.Windows.Media.VisualTreeHelper.GetChildrenCount(element); i++)
{
XElement childTree = GetVisualTree(System.Windows.Media.VisualTreeHelper.GetChild(element, i));
if (childTree != null)
myEl.Add(childTree);
}
}
return myEl;
}
제공하고 있다.
이렇게 하면 Logical & Visual Tree 를 얻을 수 있다.
(좀 편하게 위와 같은 문자열을 만들려고 "XElement"를 사용하였다.)
굉장히 중요한 개념이지만
어떻게 보면 별로 쓸때가 없을 것 같기도 하다.
하지만 알아두면 굉장히 유용하게 쓰일 때가 있다.
'Dev::DotNet > WPF' 카테고리의 다른 글
XmlnsDefinition 을 통한 namespace 매칭 (0) | 2013.11.22 |
---|---|
WPF 에서 DoEvents (0) | 2013.11.18 |
NetAdvantage XamDockManager 의 Splitter 고정 (0) | 2013.11.08 |
WPF Filter ComboBox (0) | 2013.11.04 |
XAML 에서 StringFormat 으로 문자열 표시 (0) | 2013.10.25 |