Wednesday, September 17, 2008

Silverlight Tip 7#: Handling ListBox MouseLeftButtonDown event with VisualTreeHelper

In Silverlight 2 beta 2 ListBoxItem (and ListBox) doesn’t trigger MouseLeftButtonDown event anymore! You can add handler for this event in XAML of ItemContainerStyle. I wrote post about it 9 days ago.

If you wouldn't specify the event handler in XAML, you have a problem: you can't modify code of ListBoxItem class. But you can use visual tree after loading ListBox.

You can examine the visual tree structure with VisualTreeHelper class. I have written recursive method to get all visual elements which parents are objects of a specific type:

private static List<UIElement> children = new List<UIElement>();

...

private static void GetChildrenWithParentRec(UIElement parent, Type targetType)
{
int count = VisualTreeHelper.GetChildrenCount(parent);
if (count > 0)
{
for (int i = 0; i < count; i++)
{
UIElement child = (UIElement)VisualTreeHelper.GetChild(parent, i);
if (VisualTreeHelper.GetParent(child).GetType() == targetType)
{
children.Add(child);
}
GetChildrenWithParentRec(child, targetType);
}
}
}

I have used this method to obtain visuals which are children of ListBoxItem elements of ListBox control. Before you show ListBox, you can use code:

//GetChildrenWithParent uses GetChildrenWithParentRec
List<UIElement> children = ChildrenHelper.GetChildrenWithParent(listBox, typeof(ListBoxItem));

if (children.Count > 0){
foreach (UIElement el in children)
el.MouseLeftButtonDown += new MouseButtonEventHandler(ListBoxItem_MouseLeftButtonDown);
}

It works for me.

1 comment:

matma said...

Hi Marcin,
Take power of LINQ and write less code, and also be more strongly typed...
You must read: http://zine.net.pl/blogs/procent/archive/2008/08/30/c-power-ponownie-control-allchildcontrols.aspx

Regards
Mateusz Wolsza