首页 > 解决方案 > 具有聚合值和 ProgreessBar 顺序的 WPF ListView 列

问题描述

我有包含价格、大小和总计列的 ListView。价格和尺寸列是绑定到我的项目

public ObservableCollection<MyItem> Book { get; } = new ObservableCollection<MyItem>();

在视图模型中。总列应汇总不同价格的大小,并包含结果和进度条,在最后一项上变化高达 100%。例如:

Price,Size,Total

10,2,59 (progress bar 100%)

9,6,57 (progress bar 97%)

8,5,51 (progress bar 86%)

6,34,46 (progress bar 78%)

2,12,12 (progress bar 20%)

价格有序且独一无二。但是一个问题是总数应该从下面开始。最低价格,应该是聚合时的第一项,是ListView中的最后一项。所以聚合应该使用反向的行顺序来计算,我相信。

如果 ListView 是从 ListView 中的第一项聚合的,那么我可以使用类似的东西:

例子:

Price,Size,Total

10,2,2 (progress bar 3%)

9,6,8 (progress bar 14%)

8,5,13 (progress bar 22%)

6,34,47 (progress bar 80%)

2,12,59 (progress bar 100%)
<local:SumQuantityConverter x:Key="SumQuantityConverter"/>
<DataTemplate DataType="{x:Type local:MyItem}" x:Key="MyItem.Template.ListView.Sum">
            <Grid>
                <ProgressBar x:Name="pBar" Opacity="0.3" Width="140"
                                             Minimum="0"
                                             Maximum="{Binding DataContext.Sum, ElementName=wind}">
                    <ProgressBar.Value>
                        <MultiBinding  Converter="{StaticResource SumQuantityConverter}">
                            <Binding ElementName="wind" Path="DataContext.Book" Mode="OneWay"/>
                            <Binding Path="Price" Mode="OneWay"/>
                            <Binding ElementName="wind" Path="DataContext.Sum" Mode="OneWay"/>
                        </MultiBinding>
                    </ProgressBar.Value>
                </ProgressBar>
                <TextBlock Text="{Binding Value, ElementName=pBar, Mode=OneWay}" />
            </Grid>
</DataTemplate>

<ListView ItemsSource="{Binding Book}">
            <ListView.View>
                <GridView>
                    <GridViewColumn DisplayMemberBinding="{Binding Price}" Header="Price" Width="50"/>
                    <GridViewColumn DisplayMemberBinding="{Binding Quantity}" Header="Size" Width="60"/>
                    <GridViewColumn CellTemplate="{Binding Mode=OneWay, Source={StaticResource MyItem.Template.ListView.Sum}}" Header="Total" Width="140"/>
                </GridView>
            </ListView.View>
</ListView>

转换器:

public class SumQuantityConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            if (!(values?.Length > 2))
                return null;

            if (!(values[0] is IEnumerable<MyItem> book))
                return null;

            if (!(values[1] is long price))
                return null;

            double sum = (double)book.TakeWhile(ord => ord.Price >= price).Sum(ord => ord.Quantity);

            return sum;
        }

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

当总计应该从 ListView 中的最后一项开始时,这种方法不起作用,因为我们从 ListView 的第一项开始,无法返回上一项。

你能给我一个建议,如何执行我的任务吗?

标签: c#wpflistview

解决方案


要反转ProgressBar,您可以执行以下操作

(我稍微简化了代码)

public class SumQuantityConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        if (values?.Length > 2 && values[0] is IEnumerable<MyItem> book && values[1] is long price && values[2] is long sum)
        {
            double result = (double)book.TakeWhile(ord => ord.Price > price).Sum(ord => ord.Quantity);

            return sum - result;
        }
        return null;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) => null;
}

推荐阅读