WPF Listview按数据组替换行背景而不是行

时间:2016-10-17 19:23:47

标签: c# wpf xaml listview

我无法为我的问题/想法找到解决方案,我希望有人可以帮助我。 在WPF中,我有一个CollectionViewSource,具体取决于IEnumerable<Item>Item具有名称高度年龄字段。 在Xaml中,ListView的ItemsSource="{Binding CollectionViewSource.View}"

我知道,Listview有一个AlternationCount属性,可以更改行背景颜色。

但我想仅在年龄字段数据与上述行年龄数据不同时才更改行背景颜色。

像这样,按年龄命令:

alternate

仅当年龄数据不同时才会交替行背景颜色。

当我在列表中设置另一个排序顺序时,也应该更改交替。

在此图片中,列表按名称排序:

Alternate color order name

但背景颜色取决于年龄数据。

有没有办法为这个概念提供解决方案?

2 个答案:

答案 0 :(得分:2)

您可以使用RelativeSource.PreviousData完成任务。

首先,创建一个IMultivalueConverter,它将接受您想要比较的值,并根据它们返回当前的交替指数:

class ComparisonConverter : IMultiValueConverter
{
    private int currentAlternation = 0;
    public int AlternationCount { get; set; } = 2;

    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        // TODO: exception handling
        if (values.Distinct().Count() != 1)
        {
            if (++currentAlternation >= AlternationCount)
            {
                currentAlternation = 0;
            }
        }

        return currentAlternation;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

当所有值相等时,此转换器接受多个值并返回未更改的交替索引;否则,它首先将交替索引更改为下一个,然后返回一个新索引。

现在,创建一个MultiBinding,它将为Style提供交替索引值,您可以在其中定义颜色:

<!-- This is an incomplete ListView! Set the View and ItemsSource as required. -->
<ListView>
    <ListView.Resources>
        <local:ComparisonConverter x:Key="ComparisonConverter"/>
    </ListView.Resources>
    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Style.Triggers>
                <!-- This is the DataTrigger for the alternation index 1 -->
                <DataTrigger Value="1">
                    <DataTrigger.Binding>
                        <MultiBinding Converter="{StaticResource ComparisonConverter}">
                            <Binding Path="Age"/>
                            <Binding Path="Age" RelativeSource="{RelativeSource PreviousData}"/>
                        </MultiBinding>
                    </DataTrigger.Binding>
                    <Setter Property="Background" Value="Red"/>
                </DataTrigger>
            </Style.Triggers>
            <Setter Property="Background" Value="Wheat"/>
        </Style>
    </ListView.ItemContainerStyle>
</ListView>

所以在这种风格中,交替指数0的默认颜色是小麦。使用DataTrigger,交替索引1将生成红色。

排序顺序更改将自动反映,因为CollectionViewSource将重建视图,因此ListView将使用每个项目的MultiBinding从头开始创建所有项目。

答案 1 :(得分:1)

运行这个并充分享受生活:

XAML:

<Window x:Class="WpfStackOverflow.Window6"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window6" Height="362.03" Width="563.91">

<Window.Resources>
    <CollectionViewSource x:Key="CVS" Source="{Binding .}">
        <CollectionViewSource.GroupDescriptions>
            <PropertyGroupDescription PropertyName="Age"/>
        </CollectionViewSource.GroupDescriptions>
    </CollectionViewSource>
</Window.Resources>

<Grid>
    <ListView x:Name="LstView" ItemsSource="{Binding Source={StaticResource CVS}}">
        <ListView.Resources>
            <AlternationConverter x:Key="AltCnvKey">
                <SolidColorBrush Color="Snow"/>
                <SolidColorBrush Color="LightBlue"/>
                <SolidColorBrush Color="Orange"/>
            </AlternationConverter>
        </ListView.Resources>
        <ListView.View>
            <GridView>
                <GridView.Columns>
                    <GridViewColumn DisplayMemberBinding="{Binding Name}" Header="Name"/>
                    <GridViewColumn DisplayMemberBinding="{Binding Height}" Header="Height"/>
                    <GridViewColumn DisplayMemberBinding="{Binding Age}" Header="Age"/>
                </GridView.Columns>
            </GridView>
        </ListView.View>           
        <ListView.GroupStyle>
            <GroupStyle AlternationCount="3">                    
                <GroupStyle.ContainerStyle>
                    <Style TargetType="GroupItem">
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="GroupItem">
                                    <StackPanel Orientation="Horizontal">
                                        <StackPanel.Resources>
                                            <Style TargetType="StackPanel">
                                                <Setter Property="Background" Value="{Binding RelativeSource={RelativeSource  AncestorType=GroupItem, Mode=FindAncestor}, Path=(ItemsControl.AlternationIndex), Converter={StaticResource AltCnvKey}}"/>
                                            </Style>
                                        </StackPanel.Resources>
                                        <ItemsPresenter/>
                                    </StackPanel>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>
                </GroupStyle.ContainerStyle>
            </GroupStyle>
        </ListView.GroupStyle>
    </ListView>
</Grid>

代码:

using System.Linq;
using System.Windows;

namespace WpfStackOverflow
{
    /// <summary>
    /// Interaction logic for Window6.xaml
    /// </summary>
    public partial class Window6 : Window
    {
        public Window6()
        {
            InitializeComponent();

            this.DataContext = new[] { new { Age = 32, Name = "Name1", Height = 6 }, new { Age = 34, Name = "Name1", Height = 6 }, new { Age = 34, Name = "Name1", Height = 6 }, new { Age = 32, Name = "Name1", Height = 6 }, new { Age = 32, Name = "Name1", Height = 6 }, new { Age = 39, Name = "Name1", Height = 6 }, new { Age = 40, Name = "Name1", Height = 6 } }.ToList();
        }
    }
}