看看在標準的Silverlight下和Silverlight For Windows Phone中怎樣解析元素在Visual Tree和Logical Tree中的位置。以前也過一篇在Windows 8 WinRT架構下同樣意圖的文章:WinRT/Metro:解析元素在Visual Tree和Logical Tree中的位置。由於WinRT在介面XAML上和Silverlight極為相似,因此那篇WinRT文章的代碼基本適用於Silverlight。因為不管是WinRT還是Silverlight,相比WPF,他們都沒有LogicalTreeHelper類型,UIElement的上一級也不是Visual類型,FrameworkElement沒有LogicalChildren屬性……
在Silverlight下:
兩個列表是一樣的,簡單明了(沒有像WPF那樣嵌套一大堆東西)
在Windows Phone下:
介面XAML:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock>Logical Tree</TextBlock>
<TextBlock Grid.Column="1">Visual Tree</TextBlock>
<ListBox Name="lbxLogical" Grid.Row="1"/>
<ListBox Name="lbxVisual" Grid.Row="1" Grid.Column="1"/>
</Grid>
擷取Visual Tree和Logical Tree代碼:
IEnumerable<DependencyObject> GetVisualTree(DependencyObject obj)
{
var list = new List<DependencyObject>() { obj };
var res = obj;
while ((res = VisualTreeHelper.GetParent(res)) != null)
list.Add(res);
return list.AsEnumerable().Reverse();
}
IEnumerable<DependencyObject> GetLogicalTree(DependencyObject obj)
{
var list = new List<DependencyObject>() { obj };
var res = obj;
while ((res = GetParent(res)) != null)
list.Add(res);
return list.AsEnumerable().Reverse();
}
DependencyObject GetParent(DependencyObject obj)
{
var ff = obj as FrameworkElement;
if (ff != null)
return ff.Parent;
return null;
}
最後在相應Loaded事件內執行(分別解析兩個ListBox做樣本)
lbxLogical.ItemsSource = GetLogicalTree(lbxLogical).Select(d => d.GetType().Name);
lbxVisual.ItemsSource = GetVisualTree(lbxVisual).Select(d => d.GetType().Name);