Dot Net For All

IsSelected for ListBoxItem(WPF) Template

ListBoxItem ControlTemplate

In this article I will show how we can change the ListBoxItem template for a ListBox in WPF to have a button functionality for the same where we can raise the OnClick() event as well as attach a Command to it.

You can learn about Templates here and Styles here

Add ItemTemplate to ListBoxItem

While working with the ListBox which is an ItemsControl in WPF, in which I have to change the template of the ListBoxItem by re placing the default template with a button so that I can raise an event as well as a command whenever the ListBoxItem is clicked.

There are couple of other requirements along with click and command raise, like on mouse hovering and after clicking(i.e. when the ListBoxItem is Selected) the background of the ListBoxItem should change.

<Window x:Class="SingleInstanceWPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="OnlySingle" Height="350" Width="525">
    <Window.Resources>
        <Style x:Key="ListBoxItemStyle1" TargetType="{x:Type ListBoxItem}">  
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ListBoxItem}">
                        <Border x:Name="Bd">
                            <ToggleButton IsChecked="{Binding Path=IsSelected,Mode=TwoWay,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ListBoxItem}}"
                                          Checked="ToggleButton_Checked_1">
                                <ToggleButton.Template>
                                    <ControlTemplate>
                                        <TextBlock Text="{Binding}" Background="Transparent" Foreground="Black" Margin="3 0"></TextBlock>
                                    </ControlTemplate>
                                </ToggleButton.Template>
                            </ToggleButton>
                        </Border>                   
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsSelected" Value="true">
                                <Setter Property="Background" TargetName="Bd" Value="LightBlue"/>                               
                            </Trigger>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter TargetName="Bd" Property="Background" Value="LightBlue"></Setter>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    <Grid>
        <ListBox Width="100" Height="200" 
                 ItemContainerStyle="{DynamicResource ListBoxItemStyle1}"
                 ItemsSource="{Binding ListCollection}"></ListBox>
    </Grid>
</Window>

Here I have used ToggleButton instead of Button because in case of Button there was no way to set the IsSelected property of the ListBoxItem. I could also have used the Button but when button is clicked the click event is handled at the button itself and it is not propagated up the visual tree and hence the IsSelected property of the ListBoxItem is not set and preventing from the desired behavior which we expect in our case.

The same is true for ToggleButton also but we can set the  IsSelected property of the ListBoxItem as shown in the below code snippet.

IsChecked="{Binding Path=IsSelected,Mode=TwoWay,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ListBoxItem}}"

And hence using the toggle button we should be able to set the background color for the ListBoxItem in our scenario as shown in the figure below.

The code behind for this screen for the reference is as shown below

        private List<string> listCollection;
        public MainWindow()
        {
            InitializeComponent();
            ListCollection = new List<string>() { "Item1", "item2", "item3", "item4", "Item5", "Item6", "Item7" };       
            DataContext = this;
        }

        public List<string> ListCollection 
        {
            get { return listCollection; }
            set { listCollection = value; }
        }
        
        private void ToggleButton_Checked_1(object sender, RoutedEventArgs e) { }

I Hope this article has helped you to understand how we can use controltemplate for ListBoxItem in WPF with a button which can help us to change the template as per our need.

Top career enhancing courses you can't miss

My Learning Resource

Excel your system design interview