【问题标题】:CollectionViewSource grouping, get sum(Quantity)CollectionViewSource 分组,得到 sum(Quantity)
【发布时间】:2019-01-25 06:35:21
【问题描述】:

我有一个CollectionViewSource,其来源是 ObservableCollection。

ListObservableCollection 上,我可以使用 linq 对我的对象进行分组,并对它们的数量求和,但是如何在 CollectionViewSource 上做到这一点(如果可能的话),我看不到任何文档关于它。

目前我只能使用以下方法管理分组:

ProductsView.GroupDescriptions.Add(new PropertyGroupDescription("Group"));

但我看不到有关如何显示字段的总和或最大值/最小值的信息?

编辑:

具体来说,我想做类似的事情:

liste_ass = liste_ass.GroupBy(l => l.Name)
     .Select(cl => new Assemblage
     {
         Quantite = cl.Sum(c => c.Quantite),
         ID = 0,
         IdAffaire = cl.First().IdAffaire,
         Name = cl.First().Name,
         Priorite = 0,
         Dessin = cl.First().Dessin,
         Groupe = cl.First().Groupe,
         Priorite = cl.Max(c=>c.Priorite),
         ListeIdOperations = cl.First().ListeIdOperations,
     }).ToList();

这就是我在 linq 中要做的事情。 但是阅读ICollectionView,在ICollectionView上似乎是不可能的,因为它是一个视图,不能对它们进行任何操作。

【问题讨论】:

    标签: c# wpf collectionviewsource


    【解决方案1】:

    您可以访问每个CollectionViewGroup,其中包含所有组信息,包括ItemCountCollectionView.Groups 属性。如果您想创建一个自定义组标题并在 UI 上显示它,这里有一个示例:

        <ListBox ItemsSource="{Binding your view}">
             <ListBox.Resources>
                 <local:ToAssemblageConverter x:Key="toAssemblageConverter"/>
             </ListBox.Resources>
             <ListBox.GroupStyle>
                <GroupStyle HidesIfEmpty="True">
                    <GroupStyle.HeaderTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal"
                                        DataContext="{Binding Items, Converter={StaticResource ResourceKey=toAssemblageConverter}}">
                                <TextBlock Margin="5 0" Text="{Binding Quantite}"/>
                                <TextBlock Margin="5 0" Text="{Binding Id}"/>
                                ...
                            </StackPanel>     
                        </DataTemplate>
                    </GroupStyle.HeaderTemplate>
                </GroupStyle>
            </ListBox.GroupStyle>           
        </ListBox>
    
    public class ToAssemblageConverter : IValueConverter
    {
        public object Convert (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            var cl = (IEnumerable)value;
    
            return new Assemblage() {
                Quantite = cl.Sum(c => c.Quantite),
                ID = 0,
                IdAffaire = cl.First().IdAffaire,
                Name = cl.First().Name,
                Priorite = 0,
                Dessin = cl.First().Dessin,
                Groupe = cl.First().Groupe,
                Priorite = cl.Max(c=>c.Priorite),
                ListeIdOperations = cl.First().ListeIdOperations,
            }
        }
    }
    

    【讨论】:

    • 我不想要 itemcount,假设我的 item 有一个字段“数量”,我想在字段数量中获取数量的总和。例如,如果我有一个字段“MaxPrice”,我想获取“MaxPrice”的最大值。
    • @Siegfried.V 很抱歉造成误会,CollectionViewGroup 也有Items 属性包含属于该组的所有数据项,因此您可以对它们做任何您想做的事情
    • 转换器在数据绑定中扮演着重要的角色。迟早你会需要它。而且我相信越早越好。 ^^
    • 数据转换是 wpf 数据绑定过程的一部分。 MS 为简单的数据绑定定义了IValueConverter。如果将IValueConverter 作为转换器应用于绑定,当数据绑定引擎注意到源已更新时,它会调用转换器的Convert 方法,并提供源值、目标类型、ConverterParameter(如果您分配它) , 设置为绑定目标的上一个作为参数的区域性。在大多数情况下,我们只需要关心 value 和 param,并根据它们返回值。 Bing 引擎将使用返回值来更新绑定目标。
    • 我认为这篇msdn文章docs.microsoft.com/en-us/dotnet/framework/wpf/data/…会帮助你更好地理解数据绑定。
    【解决方案2】:

    使用DynamicData 你可以这样做:

    var sourceList = new SourceList<YourType>(); // use this instead of ObservableCollection
    
    sourceList.Connect()
         .AutoRefres(x => x.Quantite) // refresh when this property changes
         .ToCollection()
         .Select(col => 
                    col
                .GroupBy(l => l.Name)
                .Select(cl => new Assemblage
                {
                    Quantite = cl.Sum(c => c.Quantite),
                    ID = 0,
                    IdAffaire = cl.First().IdAffaire,
                    Name = cl.First().Name,
                    Priorite = 0,
                    Dessin = cl.First().Dessin,
                    Groupe = cl.First().Groupe,
                    Priorite = cl.Max(c=>c.Priorite),
                    ListeIdOperations = cl.First().ListeIdOperations,
                }).ToList()
                )
           .Subscribe(col => PublicPropertyWithChangeNotification = col);
    

    当您从源列表中添加或删除项目时,它会自动更新结果,当item.Quantite 发生变化时(如果它实现了 INPC)

    【讨论】:

    • 这周你第二次跟我说这个,我去看看,我希望也有好的文档:)
    • 文档有点烂,你应该对 Rx 有所了解。良好的起点是snippets101 samples
    • 哦,还有ReactiveUI - 很棒的 UI 框架,可以自然地与 DynamicData 一起使用,因为它们都基于 Rx
    • 好吧,我想我会选择第一个选项,我不知道 Rx 是什么,我 2,3 年前开始使用 C#,一年前开始使用 MVVM,所以我还是一个纽比...
    猜你喜欢
    • 1970-01-01
    • 2021-10-03
    • 1970-01-01
    • 2012-11-04
    • 1970-01-01
    • 2021-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多