WPF provides the ability to create templated items for controls such as the list and grid.
These item templates allow any WPF controls including labels, text areas and buttons. My problem was knowing how to create code that responds to the clicks of these buttons. Wasn’t terribly obvious to me.
Here’s an example:
<DataTemplate x:Key="SomeListItemTemplate">
<StackPanel>
<TextBlock Text="{Binding Subject}" Width="188" Height="45.277"/>
<Button x:Name="cmdDeleteItem" Width="59" Height="21.277" Content="Delete" >
</StackPanel>
</DataTemplate>
The trick appears to be to create “CommandBindings”. These are an input mechanism in WPF that allows developers to define commands centrally and have them processed by the one piece of logic.
It appears this isn’t supported visually in Expression Blend unfortunately.
In order to solve my problem I had to do four things.
Firstly I defined a Window.CommandBindings section in my xaml file
<Window.CommandBindings>
<CommandBinding Command="local:MyCommands.DeleteItem" Executed="OnDeleteItem" />
</Window.CommandBindings>
(For this to work, add the ‘xmlns:local=”clr-namespace:MyProject” ‘ attribute against the Window Tag)
Secondly I created a class to host my custom command:
Public Class MyCommands
Public Shared DeleteItem As New RoutedCommand("DeleteItem", GetType(MyTasksWPF.Main))
End Class
Thirdly I created the “OnDeleteItem” method to receive my event:
Public Sub OnDeleteItem(ByVal sender As Object, ByVal args As ExecutedRoutedEventArgs)
System.Windows.MessageBox.Show("So you wanted to delete " & CStr(args.Parameter) & " punk? Well didja?")
End Sub
Finally I updated the button definition to specify the command I defined:
<Button x:Name="cmdDeleteItem" Width="59" Height="21.277" Content="Delete"
Command="local:MyCommands.DeleteItem" CommandParameter="{Binding Id}"/>
Find the SDK docummentation on the subject here:
http://www.eggheadcafe.com/software/aspnet/29895215/commandbindings-in-blend.aspx
A full example demonstrating types of using CommandBinding:
Hi,
You chose a complicated road 🙂 Try
Then in the code, create your event handler and observe the e.OriginalSource property, this is the button that was clicked.
Remember, events are bubbling 🙂
HTH,
Laurent
Sorry about non-escaping the XAML. Should read:
<ListView Button.Click=”EventHandlerName”
…
/>
Thanks worked for me great, I needed to add a button to a ListView
So to the ListView XAML I’ve added:
to the cs file I’ve added a handler:
private void Button_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show(((Button) sender).CommandParameter.ToString());
}
And it worked very well thanks guys…
I tried Laurent’s suggestion, it didn’t work for me. Exception says that XAML with events must be compiled or something. So I am going to try the commandbindings thing now.
Nice Job. I was able to use this to create a data bound treeview where each node includes a checkbox. This technique allows me to respond to the checkbox being checked and unchecked.
Fantastic! I had been searching for this for a while, it was just a matter of Googlizing the right word combination 😉
Greetings,
my DataTemplate contains a TextBox and I want to handle KeyDown or KeyPress event. Is there any way to do it with CommandBindings?
Thanks in advance.
Laurent’s suggestion worked perfectly for me. I have a ListView on my page which uses a DataTemplate defined in a seperate ResourceDictionary. I was trying to figure out a way to respond to events of controls in the DataTemplate and using event bubbling as described was exactly what I needed. Thanks!
Laurent’s way works, but i cant figure out how to identify on which ‘row’ of my ListBox the button was clicked, where as i suspect because of the CommandParameter (i’m just about to try it) the technique in this article will.
see my reply to Laurent…