views:

284

answers:

2

I have added a button to a template for a ListBoxItem. I want to know how to catch the click for the button (not selecting the ListboxItem).

The button clicks just fine in the UI, but I can't seem to find out how to wire up code so I can catch it.

I tried using:

<EventSetter Event="Click" Handler="Button_Click"></EventSetter>

but that seemed to want to be on the ListBoxItem. I could not see a way to wire it up to the button.

Here is the style I am working with incase it helps:

<Window x:Class="WIAssistant.Main"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="My App" Height="587" Width="1246" Name="MainForm" FontSize="14">

<Window.Resources>
  <Style x:Key="CheckBoxListStyle" TargetType="ListBox">
     <Style.Resources>
        <Style TargetType="ListBoxItem">
          <Setter Property="Template">
             <Setter.Value>
                 <ControlTemplate TargetType="ListBoxItem">
                   <Grid ScrollViewer.CanContentScroll="True" Margin="2">
                      <Grid.ColumnDefinitions>
                      <ColumnDefinition Width="Auto" />
                      <ColumnDefinition Width="Auto" />
                      <ColumnDefinition Width="Auto" />
                      <ColumnDefinition />
                   </Grid.ColumnDefinitions>
                   <CheckBox VerticalAlignment="Center" IsChecked="{Binding IsSelected,
                                                 RelativeSource={RelativeSource TemplatedParent},
                                                 Mode=TwoWay}" />
                   <TextBlock VerticalAlignment="Center" Grid.Column="1" Margin="5,0,5,0" Text="{Binding Id}" />
                   <TextBlock VerticalAlignment="Center" Grid.Column="2" Margin="5,0,5,0" Text="{Binding Title}" />
                   <Button HorizontalAlignment="Right" Grid.Column="3" Margin="5,0,5,0" Width="25">-&gt;</Button>
                 </Grid>
               </ControlTemplate>
             </Setter.Value>
          </Setter>
        </Style>
      </Style.Resources>
      <Setter Property="ItemsPanel">
        <Setter.Value>
           <ItemsPanelTemplate>
             <WrapPanel Orientation="Vertical"  />
           </ItemsPanelTemplate>
         </Setter.Value>
      </Setter>
    <Setter Property="BorderThickness" Value="0" />
    <Setter Property="Background" Value="Transparent" />
  </Style>
</Window.Resources>

... (In a grid in later code)

 <ListBox SelectionMode="Multiple" Style="{StaticResource CheckBoxListStyle}"
          Name="lstQueryResults" SelectionChanged="lstQueryResults_SelectionChanged">
 </ListBox>

Any way to capture the click for the button would be appreciated. (Note, just adding a click event to the button gives an error saying to use an EventSetter.

A: 

If your template were set as a data template, perhaps via a template selector, you could bind an ICommand to the button and then handle the execution of the command in your presenter/view model/whatever.

Beyond that I'm not sure, though I'm no WPF expert.

Richard Szalay
I am not a WPF expert either. Most of what you said was not concrete to me. Perhaps an example?
Vaccano
Richard Szalay
+2  A: 

The issue for the event handler seems to be the style-inside-style. Too keep the style in the window resources, try the following:

<Window.Resources>
    <DataTemplate x:Key="ListBoxItemTemplate">
        <Grid ScrollViewer.CanContentScroll="True" Margin="2">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <CheckBox VerticalAlignment="Center" IsChecked="{Binding IsSelected, Mode=TwoWay}" />
            <TextBlock VerticalAlignment="Center" Grid.Column="1" Margin="5,0,5,0" Text="{Binding Id}" />
            <TextBlock VerticalAlignment="Center" Grid.Column="2" Margin="5,0,5,0" Text="{Binding Title}" />
            <Button HorizontalAlignment="Right" Grid.Column="3" Margin="5,0,5,0" Width="25" Click="Button_Click">-&gt;</Button>
        </Grid>
    </DataTemplate>
</Window.Resources>

+

<ListBox ItemTemplate="{StaticResource ListBoxItemTemplate}" />

EventSetter in the template also works, but apparently the design view in VS stops working.

Joaquim Rendeiro
Did it compile? I got to that point as well. But when I went to compile and run it said that I needed to use an EventHandler (because it was in a style template).
Vaccano
Yup, it compiled and ran without problems. I'll post the code momentarily. By the way, I'm using .NET 3.5.
Joaquim Rendeiro
Ah, I should have posted more of my code. My bad. The XAML I posted is in <Window.Resources>. I will update my post with more of the XAML.
Vaccano
I am going to look at the code you posted. Maybe I will just use it that way.
Vaccano
The issue seems to be the style-inside-style... However you can still declare the template as a data template in the window styles with a key and then specify it as items template for the ListBox. Updating response :)
Joaquim Rendeiro
Thanks for the help! Another possible way of doing this is to attach the event to the containing ListBox (ie <ListBox Button.Click="OnButtonClick"). Because Click events bubble up, the ListBox will also get to handle it.
Vaccano