Responding To Events From DataTemplate Controls in WPF

Standard

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:

http://adoguy.com/2007/03/28/WPF_Command_Example.aspx

10 responses »

  1. 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

    • 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…

  2. 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.

  3. 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.

  4. Fantastic! I had been searching for this for a while, it was just a matter of Googlizing the right word combination 😉

  5. 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!

  6. 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.

Leave a comment