Search code examples
wpfxamlcontroltemplatelistviewitem

WPF- How to refactor multiple ListViewItem Style Template with few changes?


I'm using custom style selector on list view to change CornerRadius / BorderThickness for first and last item.

I need to have this presentaion with Enum binding on listview enter image description here

Code of the list view with ItemContainerStyleSelector

<ListView ItemsSource="{Binding ItemsSource, ElementName=Self, Mode=TwoWay}" 
              FocusVisualStyle="{x:Null}"
              BorderThickness="0"
              SelectedValue="{Binding SelectedValue, ElementName=Self, Mode=TwoWay}" 
              HorizontalAlignment="Stretch"
              ScrollViewer.VerticalScrollBarVisibility="Disabled"
              ScrollViewer.HorizontalScrollBarVisibility="Disabled"
              Background="Transparent">
            <ListView.ItemContainerStyleSelector>
                <enumToggleButtonList:FirstLastItemStyleSelector 
                    DefaultStyle="{StaticResource AllItemStyle}"
                    StyleFirst="{StaticResource FirstItemStyle}" 
                    StyleLast="{StaticResource LastItemStyle}"/>
            </ListView.ItemContainerStyleSelector>
            <ListView.ItemsPanel>
                <ItemsPanelTemplate>
                    <UniformGrid FlowDirection="LeftToRight" Rows="1"/>
                </ItemsPanelTemplate>
            </ListView.ItemsPanel>
        </ListView>

I have 3 styles : default / first / last like this

        <Style x:Key="AllItemStyle" TargetType="ListViewItem">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ListViewItem">
                        <Border x:Name="TemplateBorder" 
                                Style="{StaticResource BorderListViewItemStyle}" 
                                CornerRadius="0" 
                                BorderThickness="1,1,0,1">
                            <TextBlock x:Name="TemplateTextBlock" 
                                       Text="{Binding}" 
                                       Style="{StaticResource TextblockListViewItemStyle}"/>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsSelected" Value="True">
                                <Setter TargetName="TemplateBorder" Property="Style" Value="{StaticResource SelectedBorderListViewItemStyle}"/>
                                <Setter TargetName="TemplateTextBlock" Property="Style" Value="{StaticResource SelectedTextblockListViewItemStyle}"/>
                            </Trigger>
                            <Trigger Property="IsSelected" Value="False">
                                <Setter  TargetName="TemplateBorder" Property="Style" Value="{StaticResource BorderListViewItemStyle}"/>
                                <Setter TargetName="TemplateTextBlock" Property="Style" Value="{StaticResource TextblockListViewItemStyle}"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <EventSetter Event="PreviewMouseLeftButtonDown" Handler="ListViewItem_PreviewMouseLeftButtonDown" />
        </Style>
        <Style x:Key="LastItemStyle" TargetType="ListViewItem">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ListViewItem">
                        <Border x:Name="TemplateBorder" 
                                Style="{StaticResource BorderListViewItemStyle}" 
                                CornerRadius="0,5,5,0">
                            <TextBlock x:Name="TemplateTextBlock"
                                       Text="{Binding}" 
                                       Style="{StaticResource TextblockListViewItemStyle}"/>
                        </Border>
                        .... same
        </Style>
        <Style x:Key="FirstItemStyle" TargetType="ListViewItem">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ListViewItem">
                        <Border x:Name="TemplateBorder" 
                                Style="{StaticResource BorderListViewItemStyle}" 
                                CornerRadius="5,0,0,5" 
                                BorderThickness="1,1,0,1">
                            <TextBlock x:Name="TemplateTextBlock" 
                                       Text="{Binding}" 
                                       Style="{StaticResource TextblockListViewItemStyle}"/>
                        </Border>
                       .... same
        </Style>

And globally changes are for the border :

 <Border x:Name="TemplateBorder" 
                                Style="{StaticResource BorderListViewItemStyle}" 
                                CornerRadius="5,0,0,5" 
                                BorderThickness="1,1,0,1">

There are any methods to refactor this without using code behind plz ? Or another way to do that ?


Solution

  • The most simplest /sexy solution to do that is for the moment TemplateBinding ... I just discovered how it work ... learning is hard .. but the way after is easier x)

    <Style x:Key="AllItemStyle" TargetType="ListViewItem">
        <Setter Property="Border.CornerRadius" Value="0"/>
        <Setter Property="BorderThickness" Value="1"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ListViewItem">
                    <Border x:Name="TemplateBorder" 
                            Style="{StaticResource BorderListViewItemStyle}" 
                            CornerRadius="{TemplateBinding Border.CornerRadius}"
                            BorderThickness="{TemplateBinding BorderThickness}">
                        <TextBlock x:Name="TemplateTextBlock" 
                                   Text="{Binding}" 
                                   Style="{StaticResource TextblockListViewItemStyle}"/>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter TargetName="TemplateBorder" Property="Style" Value="{StaticResource SelectedBorderListViewItemStyle}"/>
                            <Setter TargetName="TemplateTextBlock" Property="Style" Value="{StaticResource SelectedTextblockListViewItemStyle}"/>
                        </Trigger>
                        <Trigger Property="IsSelected" Value="False">
                            <Setter  TargetName="TemplateBorder" Property="Style" Value="{StaticResource BorderListViewItemStyle}"/>
                            <Setter TargetName="TemplateTextBlock" Property="Style" Value="{StaticResource TextblockListViewItemStyle}"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <EventSetter Event="PreviewMouseLeftButtonDown" Handler="ListViewItem_PreviewMouseLeftButtonDown" />
    </Style>
    <Style x:Key="LastItemStyle" TargetType="ListViewItem" BasedOn="{StaticResource AllItemStyle}">
        <Setter Property="Border.CornerRadius" Value="0,10,10,0"/>
    
    </Style>
    <Style x:Key="FirstItemStyle" TargetType="ListViewItem" BasedOn="{StaticResource AllItemStyle}">
        <Setter Property="Border.CornerRadius" Value="10,0,0,10"/>
        <Setter Property="BorderThickness" Value="1,1,0,1"/>