Now this may be more trouble than it's worth but nevertheless, it'd be really useful to me right now.
What I'd like to know is how I might go about manipulating the Silverlight visual tree at runtime. Doing simple things like adding and removing controls is easy enough but when you start having to traverse the tree with any reasonable amount of complexity I find myself yearning for a JQuery style syntax (LINQ would be pretty cool too I suppose) to handle DOM node replacements, movements and the like.
So I guess the question is are there any libraries out there to make this an easier job or is there something baked in that I've missed?
Yes Linq extension methods are what you are after but you need to put inplace a litte infrastructure first:-
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);
}
}
}
Now you can use Linq to query into the visual tree using Linq. Some examples:-
// 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");