Search code examples
c#wpfdatatriggerlistboxitem

WPF: Custom ListBoxItem with CheckBox - Strike through text on Checked


i am writing a simple todo list, i have a class TaskItem which contains the property "Completed", the class implements the inotifypropertychanged on the class and all properties.

What i am after is being able to set a DataTrigger so when the checkbox is checked/unchecked the Text is strike through-ed.

my listbox code is below:

            <ListBox x:Name="TaskListBox" Background="#FF515658" Cursor="Arrow">
                <ListBox.ItemContainerStyle>
                    <Style TargetType="ListBoxItem">
                        <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
                        <Setter Property="Focusable" Value="False"/>
                    </Style>
                </ListBox.ItemContainerStyle>
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="Auto"/>
                                    <ColumnDefinition Width="*"/>
                                    <ColumnDefinition Width="Auto"/>
                                </Grid.ColumnDefinitions>
                                <CheckBox Name="CheckBoxZone" Tag="{Binding ID}" IsChecked="{Binding Completed}" Margin="0 0 0 0" Grid.Column="0"/>
                                <TextBlock  x:Name="TaskNameLabel" Text="{Binding Name}" Foreground="White"  Margin="10 -1 0 0" Grid.Column="1"/>
                                <Image x:Name="DelTaskButtom" Margin="8 -1 10 0" Height="10px" Width="10px" Source="../Resources/Delete.png" Cursor="Hand" Grid.Column="2" Visibility="Hidden" PreviewMouseLeftButtonDown="TaskListBoxItem_DeleteTask"/>
                       </Grid>
                            <DataTemplate.Triggers>
                                <DataTrigger Binding="{Binding IsMouseOver,RelativeSource={RelativeSource TemplatedParent}}" Value="True">
                                    <Setter Property="Visibility" TargetName="DelTaskButtom" Value="Visible" />
                                </DataTrigger>


                            <DataTrigger Binding="{Binding IsChecked,RelativeSource={RelativeSource AncestorType={x:Type CheckBox}}}" Value="True">
                                    <Setter Property="TextBlock.TextDecorations" Value="Strikethrough" />
                            </DataTrigger>
                        </DataTemplate.Triggers>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

Can anyone help me with this? can i do it through XAML or do i need to set events and do it through the code side of things.


Solution

  • The problem is in Binding in your Trigger. You can't use relative source in DataTemplate trigger. The other problem is the setter. You have to specify TargetName.

    There are two options how to write your trigger in DataTemplate:

    Using DataTrigger:

    <DataTrigger Binding="{Binding Completed}" Value="True">
       <Setter TargetName="TaskNameLabel" Property="TextDecorations" Value="Strikethrough" />
    </DataTrigger>
    

    or using Trigger

    <Trigger SourceName="CheckBoxZone" Property="IsChecked" Value="True">       
        <Setter TargetName="TaskNameLabel" Property="TextDecorations" Value="Strikethrough" />
    </Trigger>
    

    the setter is the same in both cases