How can I override the ContentTemplate ListView to add a vertical separator?

I want to change the WPF ListView so that the elements are displayed horizontally, and there is a separator between the first element and all subsequent elements. Something like that:A horizontal list with a split first item

I have a horizontal bit, but I am stuck with a delimiter. I tried using a DataTemplate, but this includes the separator in the actual element, which means that it is highlighted when you hover over (note that I am using Caliburn, but I do not think this will greatly affect the question):

<UserControl.Resources>
    <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</UserControl.Resources>
<StackPanel Margin="20">
    <ListView Name="Items" BorderThickness="0">
        <ListView.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <ContentControl cal:View.Model="{Binding}" />
                    <Border Name="Separator" Width="2" Margin="5,10" HorizontalAlignment="Center" Background="Red" Visibility="{Binding IsFirst, Converter={StaticResource BooleanToVisibilityConverter}}" />
                </StackPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
        <ListView.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Horizontal" />
            </ItemsPanelTemplate>
        </ListView.ItemsPanel>
    </ListView>
</StackPanel>

Elements are very simple representations with this border:

<Border Background="White" BorderBrush="Black" BorderThickness="2">

What the DataTemplate looks like:

Wrong selector selection

After reading the templates in the morning, I decided that the ControlTemplate is the solution that after the struggle gave me this code:

<UserControl.Resources>
    <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
    <Style TargetType="ListViewItem">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ListViewItem">
                    <StackPanel Margin="10" Orientation="Horizontal">
                        <ContentPresenter Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" />
                        <Border Name="Separator" Width="2" Margin="5,10" HorizontalAlignment="Center" Background="Red" Visibility="{Binding IsFirst, Converter={StaticResource BooleanToVisibilityConverter}}" />
                    </StackPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</UserControl.Resources>
<StackPanel>
    <ListView Name="Items">
        <ListView.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Horizontal" />
            </ItemsPanelTemplate>
        </ListView.ItemsPanel>
    </ListView>
</StackPanel>

, - . , , , ControlTemplate.Triggers : WPF ListViewItem, , .

, , ControlTemplate ?

EDIT: , xaml.

+4
3

public class MyPanel : StackPanel
{
    static MyPanel()
    {
        OrientationProperty.OverrideMetadata(typeof(MyPanel), new FrameworkPropertyMetadata(Orientation.Horizontal));
    }

    protected override void OnRender(DrawingContext dc)
    {
        base.OnRender(dc);
        if (Children.Count >= 2)
        {
            var child = Children[0] as FrameworkElement;
            if (child != null)
                dc.DrawLine(new Pen(Brushes.Red, 2), new Point(child.ActualWidth + 2, 5), new Point(child.ActualWidth + 2, ActualHeight - 5));
        }
    }
}

<ListView.ItemsPanel>
    <ItemsPanelTemplate>
        <local:MyPanel/>
    </ItemsPanelTemplate>
</ListView.ItemsPanel>

/ , , .

+2

ItemTemplateSelector, .

, . , . .

, .

0

I was able to figure out how to re-add triggers (which, as I confirmed, disappeared without using my new favorite WPF WPF Inspector tool ). Once this was done, the final problem was that the separator also fired the mouse event for the event for the first element which I fixed by targeting the inner border:

<UserControl.Resources>
    <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
    <Style TargetType="ListViewItem">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ListViewItem">
                    <StackPanel Orientation="Horizontal">
                        <Border x:Name="ItemBorder" Padding="2">
                            <StackPanel>
                                <ContentPresenter />
                            </StackPanel>
                        </Border>
                        <Border Name="Separator" Width="2" Margin="5,10" HorizontalAlignment="Center" Background="Red" Visibility="{Binding IsFirst, Converter={StaticResource BooleanToVisibilityConverter}}" />
                    </StackPanel>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter TargetName="ItemBorder" Property="Border.Background" Value="Blue" />
                            <Setter TargetName="ItemBorder" Property="Border.BorderBrush" Value="Green" />
                        </Trigger>
                        <DataTrigger Binding="{Binding ElementName=ItemBorder, Path=IsMouseOver}" Value="True">
                            <Setter TargetName="ItemBorder" Property="Border.Background" Value="Yellow" />
                        </DataTrigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</UserControl.Resources>
<StackPanel>
    <ListView Name="Items">
        <ListView.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Horizontal" />
            </ItemsPanelTemplate>
        </ListView.ItemsPanel>
    </ListView>
</StackPanel>

For some unknown reason, the ItemBorder element needs to be complemented by 2, otherwise the border cannot be visible.

0
source

Source: https://habr.com/ru/post/1682861/


All Articles