WPF隐藏重复与CollectionViewSource

本文关键字:CollectionViewSource 隐藏 WPF | 更新日期: 2023-09-27 18:02:37

我有一个ObservableCollection<M> fooBar {get;set;}。类M.cs看起来像这样:

public class M{
    private int _ID;
    public int ID {
        get {return this._ID;}
        set {this._ID = value;}
    }
    private string _number;
    public int Number {
        get {return this._number;}
        set {this._number = value;}
    }
    private string _power;
    public int Power {
        get {return this._power;}
        set {this._power = value;}
    }
    /*
       ...
    */
}   

现在我只想隐藏属性Power的重复项。在我的.xaml代码中,我这样写:

<UserControl.Resources>
    <CollectionViewSource x:Key="myCollection" Source="{Binding Path=fooBar}">
        <CollectionViewSource.GroupDescriptions>
            <PropertyGroupDescription PropertyName="Power"/>
        </CollectionViewSource.GroupDescriptions>
    </CollectionViewSource>
</UserControl.Resources>

我将这个集合绑定到我的ComboBox

<ComboBox Name="cbValues" 
    ItemsSource="{Binding Source={StaticResource myCollection}}"
    DisplayMemberPath="{Binding Power}" 
    SelectedValuePath="{Binding Power}"
    />

ComboBox填充了正确的值,但仍然存在重复。我怎样才能把它们藏起来?

WPF隐藏重复与CollectionViewSource

你可以试试CollectionViewSource.Filter

myCollection.Filter+= new FilterEventHandler(ShowOnlyDistinctFilter);

此事件处理程序用于筛选和显示与数据源相关的数据

private void ShowOnlyDistinctFilter(object sender, FilterEventArgs e)
{
    var item= e.Item as M;
    if (item != null)
    {
       //Your distinct logic here
    }
}

我也有这个问题,但找不到一个好的答案,所以这里是我想到的通用解决方案。

可以很好地与多个CollectionViewSource一起工作,至少在我的情况下,每个CollectionViewSource需要在不同的对象上是不同的。

这是泛型方法:

您只需要确保T是与CollectionViewSource.Source相同的类型。

    private void cvs_filter_distinct<T>(CollectionViewSource sender, FilterEventArgs e, Func<T, T, bool> arg)
    {
        if (e.Item != null)
        {
            switch (sender.View.IsEmpty)
            {
                case true:
                    e.Accepted = true;
                    break;
                default:       
                    switch ((sender.View.Cast<T>()).All(x => arg(x, (T)e.Item)))
                    {
                        case true:
                            e.Accepted = true;
                            break;
                        default:
                            e.Accepted = false;
                            break;
                    }  
                    break;
            }     
        }
    }
示例:

给定如下对象:

    public class My_Class
    {
        public string String_A { get; set; }
        public string String_B { get; set; }
    }

使用数据集合和CollectionViewSource,如:

    public ObservableCollection<My_Class> My_Data_Collection = new ObservableCollection<My_Class>();
    public CollectionViewSource My_CollectionViewSource = new CollectionViewSource();

我们添加了通用过滤器,并且"curry"Function via lambda:

public void Some_Methood()
    {
        My_CollectionViewSource.Source = My_Data_Collection;

        My_CollectionViewSource.Filter += 
            new FilterEventHandler(
                (sender, e) => cvs_filter_distinct<My_Class>(
                    sender:(CollectionViewSource)sender, 
                    e: e, 
                    arg: (a, b) => a.String_A != b.String_A));

    }   

对我来说这很好,因为我可以指定要比较的对象以及如何比较它们。此外,我不必为每个CollectionViewSource编写单独的筛选方法。

如果你想更花哨,你可以扩展它来过滤基于项目在另一个集合,像这样:

    private void cvs_filter_distinct<T, O>(CollectionViewSource sender, FilterEventArgs e, Func<T, O, bool> arg, O[] otherCollection)
    {
        T[] _view_values;
        if (e.Item != null)
        {
            switch (sender.View.IsEmpty)
            {
                case true:
                    e.Accepted = true;
                    break;
                default:
                    _view_values =
                        sender
                        .View
                        .Cast<T>()
                        .ToArray();
                    e.Accepted =
                        otherCollection
                        .All(a => _view_values
                            .All(a2 => arg(a2, a)));
                    break;
            }
        }
    }
    private class My_Other_Class
    {
        public string Another_String { get; set; }
    }

    public void Some_Other_Methood()
    {
        My_Other_Class[] my_other_data_collection = new My_Other_Class[] {
            new My_Other_Class() {
                Another_String = "some other text" } };
        
        My_CollectionViewSource.Source = My_Data_Collection;
        
        My_CollectionViewSource.Filter +=
            new FilterEventHandler(
                (sender, e) => cvs_filter_distinct<My_Class,My_Other_Class>(
                    sender: (CollectionViewSource)sender,
                    e: e,
                    arg: (a, b) => a.String_A != b.Another_String,
                    otherCollection: my_other_data_collection));

    }
相关文章:
  • 没有找到相关文章