Informhunter
Informhunter

Reputation: 59

How to add a "click" handler to a button which is a part of control template?


I have a control template: (1)

<Style x:Key="customItemStyle">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ListBoxItem}">
                <ToggleButton>
                    <Grid Width="260" Height="58">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="58"/>
                            <ColumnDefinition Width="202"/>
                        </Grid.ColumnDefinitions>
                        <Image Grid.Column="0" Source="{StaticResource image_resourse}"/>
                        <Button Grid.Column="1"> Button text </Button>
                    </Grid>
                </ToggleButton>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

It is used to customize ListBoxItems like this: (2)

<ListBox>
    ...
    <ListBoxItem Style="{StaticResource customItemStyle}">
    ...
</ListBox

I want to set Click handler of a Button which is inside that template when applying style to ListBoxItem. (1) - code from styles file (2) - code from some component definition file

How can I do this?

Upvotes: 4

Views: 3252

Answers (2)

rajibdotnet
rajibdotnet

Reputation: 1596

You need to make a slight variation to apply the style. Button_Click can be handled

<Window.Resources>
        <Style x:Key="{x:Type ListBoxItem}" TargetType="ListBoxItem">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ListBoxItem}">
                        <ToggleButton>
                            <Grid Width="260" Height="58">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="58"/>
                                    <ColumnDefinition Width="202"/>
                                </Grid.ColumnDefinitions>
                                <Image Grid.Column="0" Source="{StaticResource image_resourse}"/>
                                <Button Grid.Column="1" Click="Button_Click">Button text</Button>
                            </Grid>
                        </ToggleButton>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>

<Grid>       
        <ListBox >
            <ListBoxItem>0ABC</ListBoxItem>
            <ListBoxItem>1ABC</ListBoxItem>
            <ListBoxItem>2ABC</ListBoxItem>
        </ListBox>
</Grid>

Inside xaml.cs, button click can be handled

private void Button_Click(object sender, RoutedEventArgs e)
 {
    MessageBox.Show("E hoooo");
 }

Upvotes: 0

McGarnagle
McGarnagle

Reputation: 102723

The way to do this is to define an ICommand on the template. That way, you should have no trouble binding the handler to whatever code you need.

Start by subclassing ListBoxItem, and include the "ICommand" dependency property:

public class CommandListBoxItem : ListBoxItem 
{
    public static readonly DependencyProperty ButtonCommandProperty = 
        DependencyProperty.Register("ButtonCommand", typeof(ICommand), typeof(CommandListBoxItem), null);
    public bool ButtonCommand
    {
        get { return (ICommand)GetValue(ButtonCommandProperty); }
        set { SetValue(ButtonCommandProperty, value); }
    }

    public CommandListBoxItem()
    {
        DefaultStyleKey = typeof(CommandListBoxItem);
    }
}

Now modify the control template to link the command to the button click:

<Style x:Key="customItemStyle">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type custom:CommandListBoxItem}">
                <ToggleButton>
                    <Grid Width="260" Height="58">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="58"/>
                            <ColumnDefinition Width="202"/>
                        </Grid.ColumnDefinitions>
                        <Image Grid.Column="0" Source="{StaticResource image_resourse}"/>
                        <Button Grid.Column="1" Command="{TemplateBinding ButtonCommand}"> Button text </Button>
                    </Grid>
                </ToggleButton>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

And finally, bind the command property to a command in your view-model (or code-behind):

<ListBox>
    ...
    <custom:CommandListBoxItem Style="{StaticResource customItemStyle}" 
                               ButtonCommand="{Binding CommandFromViewModel}" />
    ...
</ListBox>

Upvotes: 3

Related Questions