Gnah
Gnah

Reputation: 16

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 ?

Upvotes: 0

Views: 97

Answers (2)

Gnah
Gnah

Reputation: 16

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"/>

Upvotes: 0

Keithernet
Keithernet

Reputation: 2509

You can simplify your styles by utilizing attached properties. But that does require you creating a simple attached properties class.

using System.Windows;

namespace SO
{
    public static class ListViewItemProperties
    {
        public static readonly DependencyProperty CornerRadiusProperty =
            DependencyProperty.RegisterAttached(
                "CornerRadius",
                typeof(Thickness),
                typeof(ListViewItemProperties),
                new PropertyMetadata(new Thickness(0d)));

        public static Thickness GetCornerRadius(DependencyObject obj)
        {
            return (Thickness)obj.GetValue(CornerRadiusProperty);
        }

        public static void SetCornerRadius(DependencyObject obj, Thickness value)
        {
            obj.SetValue(CornerRadiusProperty, value);
        }
    }
}

And there are the updated (and simplified) styles that use the attached property:

<Style x:Key="AllItemStyle" TargetType="ListViewItem">
    <Setter Property="local:ListViewItemProperties.CornerRadius" Value="0" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ListViewItem">
                <Border x:Name="TemplateBorder"
                    BorderThickness="1,1,0,1"
                    CornerRadius="{TemplateBinding local:ListViewItemProperties.CornerRadius}"
                    Style="{StaticResource BorderListViewItemStyle}">
                    <TextBlock x:Name="TemplateTextBlock"
                        Style="{StaticResource TextblockListViewItemStyle}"
                        Text="{Binding}" />
                </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" BasedOn="{StaticResource AllItemStyle}" TargetType="ListViewItem">
    <Setter Property="local:ListViewItemProperties.CornerRadius" Value="0,5,5,0" />
</Style>

<Style x:Key="FirstItemStyle" BasedOn="{StaticResource AllItemStyle}" TargetType="ListViewItem">
    <Setter Property="local:ListViewItemProperties.CornerRadius" Value="5,0,0,5" />
</Style>

Upvotes: 1

Related Questions