What I wanted to do was be able to bind a name and delegate function to a custom menu item.
[ListBox x:Name="ItemList" Width="Auto" Height="Auto"]
[ListBox.ItemTemplate]
[DataTemplate]
[StackPanel Orientation="Horizontal"]
[TextBlock Text="{Binding itemname}"
FontFamily="Arial" Font Foreground="Black"
MouseLeftButtonDown="{Binding itemaction}"/]
[/StackPanel]
[/DataTemplate]
[/ListBox.ItemTemplate]
[/ListBox]
But I was getting a compiler error:
Error 5 The "ValidateXaml" task failed unexpectedly.
System.InvalidOperationException: Stack empty.
at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
at System.Collections.Generic.Stack`1.Pop()...
After a quick trip to the Silverlight forums I found out that you cannot databind to an event handler - which made some sense after I found this on the MSDN page for DataBinding:
The binding engine gets information from the Binding object about the following:
The target UI property that displays and possibly allows user changes to the data. The target can be any DependencyProperty of a FrameworkElement.
My Solution: Sneak the function delegate into the tag property
Since I couldn't bind the event directly I decided to sneak the delegate into the tag property of the textbox, and then setup a generic mouseLeftButtonDown handler that would read out the tag and cast it to my delegate, and then invoke it. So far it seems to work pretty well.
[ListBox x:Name="ItemList" Width="Auto" Height="Auto"]
[ListBox.ItemTemplate]
[DataTemplate]
[StackPanel Orientation="Horizontal"]
[TextBlock Text="{Binding itemname}"
FontFamily="Arial" Font Foreground="Black"
Tag="{Binding itemaction}"
MouseLeftButtonDown="TextBlock_MouseLeftButtonDown" /]
[/StackPanel]
[/DataTemplate]
[/ListBox.ItemTemplate]
[/ListBox]
and then in the code behind:
private void TextBlock_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// Get the tag info and run it.
MenuActionDelegate func = ((FrameworkElement) sender).Tag as MenuActionDelegate;
func.Invoke();
}
If anyone else has a more elegant solution, please let me know!!!
.
3 comments:
In the mouse click event handler, the DataContext property of the TextBlock you've clicked (the sender) will have a reference to the object it was bound to. So...
((sender as TextBlock).DataContext as YourClass).itemaction.Invoke() should work without using the tag at all.
You can use the extension library from Microsoft, Microsoft.Practices.Composite, and the other supporting libraries which are also part of the prism framework. Using the framework you can implement the Attached Behaviors pattern.
Command Pattern and Practices:
http://msdn.microsoft.com/en-us/library/dd458928.aspx
Prism:
http://blogs.msdn.com/bobbrum/
Thank you! I'll have a look into that :)
Post a Comment