现在这可能比它的价值更麻烦,但尽管如此,它现在对我来说真的很有用。
我想知道的是如何在运行时操作 Silverlight 可视化树。做一些简单的事情,比如添加和删除控件很容易,但是当你开始以任何合理的复杂程度遍历树时,我发现自己渴望使用 JQuery 样式语法(我想 LINQ 也很酷)来处理 DOM 节点替换,动作等。
所以我想问题是是否有任何图书馆可以让这项工作变得更容易,或者是否有一些我错过的东西?
现在这可能比它的价值更麻烦,但尽管如此,它现在对我来说真的很有用。
我想知道的是如何在运行时操作 Silverlight 可视化树。做一些简单的事情,比如添加和删除控件很容易,但是当你开始以任何合理的复杂程度遍历树时,我发现自己渴望使用 JQuery 样式语法(我想 LINQ 也很酷)来处理 DOM 节点替换,动作等。
所以我想问题是是否有任何图书馆可以让这项工作变得更容易,或者是否有一些我错过的东西?
是的 Linq 扩展方法是您所追求的,但您需要先放置一个小型基础设施:-
public static class VisualTreeEnumeration
{
public static IEnumerable<DependencyObject> Descendents(this DependencyObject root, int depth)
{
int count = VisualTreeHelper.GetChildrenCount(root);
for (int i = 0; i < count; i++)
{
var child = VisualTreeHelper.GetChild(root, i);
yield return child;
if (depth > 0)
{
foreach (var descendent in Descendents(child, --depth))
yield return descendent;
}
}
}
public static IEnumerable<DependencyObject> Descendents(this DependencyObject root)
{
return Descendents(root, Int32.MaxValue);
}
public static IEnumerable<DependencyObject> Ancestors(this DependencyObject root)
{
DependencyObject current = VisualTreeHelper.GetParent(root);
while (current != null)
{
yield return current;
current = VisualTreeHelper.GetParent(current);
}
}
}
现在您可以使用 Linq 使用 Linq 查询可视化树。一些例子:-
// Get all text boxes in usercontrol:-
this.Descendents().OfType<TextBox>();
// All UIElement direct children of the layout root grid:-
LayoutRoot.Descendents(0).OfType<UIElement>();
// Find the containing `ListBoxItem` for an element:-
elem.Ancestors().OfType<ListBoxItem>.FirstOrDefault();
// Seek button with name "PinkElephants" even if outside of the current Namescope:-
this.Descendents()
.OfType<Button>()
.FirstOrDefault(b => b.Name == "PinkElephants");
您可能对此LINQ to Visual Tree实现感兴趣。
这是什么版本的银光?这个帖子是哪一年的“12 月 13 日 13:13”?
在当前版本的 SL4 中,它似乎不存在..
我使用此代码从可视化树中获取控件
public static FrameworkElement GetComponent(object child, Type t, Type bailOn)
{
if (child == null) return null;
DependencyObject control = (DependencyObject)child; // VisualTreeHelper.GetParent((DependencyObject)x);
while (control != null)
{
if (!control.Equals(child))
{
if (control.GetType() == t)
{
break;
}
}
if (control is FrameworkElement)
{
control = (control as FrameworkElement).Parent;
}
else if ((control is DataGridBoundColumn)) // data grid fucken columns
{
control = GetDataGridBoundColumnDataGrid(control);
}
if (control != null && bailOn != null && bailOn.GetType() == control.GetType())
{
return null;
}
}
// try VTH as we did not find it, as that works some times and the above does not
if (control == null)
{
control = (DependencyObject)child; // start again
while (control != null)
{
if (!control.Equals(child))
{
if (control.GetType() == t)
{
break;
}
}
if (control is FrameworkElement)
{
control = VisualTreeHelper.GetParent((control as FrameworkElement));
}
else if (control is DataGridBoundColumn)
{
control = GetDataGridBoundColumnDataGrid(control);
}
if (control != null && bailOn != null && bailOn.GetType() == control.GetType())
{
return null;
}
}
}
return control as FrameworkElement;
}
public static List<FrameworkElement> GetComponentsByType(FrameworkElement parent, Type type)
{
List<FrameworkElement> controls = new List<FrameworkElement>();
GetComponentsByTypeWorker(parent, type, controls);
return controls;
}
private static void GetComponentsByTypeWorker(FrameworkElement parent, Type type, List<FrameworkElement> controls)
{
if (parent.GetType() == type)
{
controls.Add(parent as FrameworkElement);
}
int cnt = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < cnt; i++)
{
FrameworkElement child = VisualTreeHelper.GetChild(parent, i) as FrameworkElement;
if (child.GetType() == type)
{
controls.Add(child as FrameworkElement);
}
int cnt2 = VisualTreeHelper.GetChildrenCount(child);
for (int j = 0; j < cnt2; j++)
{
FrameworkElement child2 = VisualTreeHelper.GetChild(child, j) as FrameworkElement;
GetComponentsByTypeWorker(child2 as FrameworkElement, type, controls);
}
}
}