现在这个可能比它的价值更麻烦但是,它现在对我来说真的很有用。
我想知道的是如何在运行时操作Silverlight可视化树。做一些简单的事情,比如添加和删除控件都很容易,但是当你开始以任何合理的复杂度遍历树时,我发现自己渴望使用JQuery样式语法(我认为LINQ也很酷)来处理DOM节点替换,动作等。
所以我想问题是,是否有任何图书馆可以让这项工作变得更容易,或者是否有我遗漏的东西?
答案 0 :(得分:6)
是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");
答案 1 :(得分:2)
您可能对此LINQ to Visual Tree实施感兴趣。
答案 2 :(得分:0)
这是什么版本的silverlight? 那个“12月13日13:13”的这一年的帖子是什么?
在当前版本的SL4中似乎没有......
答案 3 :(得分:0)
我使用此代码从可视树中获取控件
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);
}
}
}