WPF 将过滤后的 ObservableCollection ICollectionView 绑定到 Combobox

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17387506/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 09:06:19  来源:igfitidea点击:

WPF Binding filtered ObservableCollection ICollectionView to Combobox

c#wpfmvvm-lightobservablecollectionicollectionview

提问by FloppyDisk

I want to filter an ObservableCollection to a subset based on type (type AddPoint) and want it ordered ascending with no duplicates. My base class is ModelBase, w/ sub-classes AddPoint, Time, Repeat, etc... The ObservableCollection MotionSequenceCollection will be filled w/ those types in any order and some will be duplicates.

我想将 ObservableCollection 过滤为基于类型(AddPoint 类型)的子集,并希望它升序排序,没有重复项。我的基类是 ModelBase,带有子类 AddPoint、Time、Repeat 等...... ObservableCollection MotionSequenceCollection 将按任何顺序填充这些类型,有些将是重复的。

I've tried several different times and shown them below in the ICollectionView Property that I 'pulled' from: Bind subset of collection.

我已经尝试了几次不同的时间,并在我“拉出”的 ICollectionView 属性中显示了它们: 绑定集合的子集

OBSERVABLE COLLECTION

可观察的集合

private ObservableCollection<ModelBase> _motionSequenceCollection = 
        new ObservableCollection<ModelBase>();

    public ObservableCollection<ModelBase> MotionSequenceCollection
    {
        get
        {
            return _motionSequenceCollection;
        }

        set
        {
            if (_motionSequenceCollection == value)
            {
                return;
            }

            var oldValue = _motionSequenceCollection;
            _motionSequenceCollection = value;

            // Update bindings, no broadcast
            RaisePropertyChanged();
        }
    }

    public ICollectionView Location
    {
        get
        {
             var location = CollectionViewSource.GetDefaultView(_motionSequenceCollection);

            //DOES NOT WORK.  PROBLEM: GetType() creates type of system.type() and AddPoint, which don't work.  Need a cast, or something??  
            // found at https://stackoverflow.com/questions/9621393/bind-subset-of-collection  The problem is that there is an error:
            //    Cannot apply operator '==' to operands of type 'System.Type' and 'MotionSeq.Model.AddPoint',
            //    candidates are:
            //          bool ==(System.Reflection.MemberInfo, System.Reflection.memberInfo) (in class MemberInfo)
            //          bool ==(System.type, System.Type) (in class Type)
            //location.Filter = p => (p as ModelBase).GetType() == AddPoint;

            //DOES NOT WORK.  PROBLEM: Affects the main collection and won't let TIME type added.
            //location.Filter = o1 => (o1 is AddPoint);

            //DOES NOT WORK.  PROBLEM: Sorts fine, but also sorts MotionSequenceCollection!!  What up w/ that!?  
            //location.SortDescriptions.Add(new SortDescription("AddPointClassName", ListSortDirection.Ascending));

            //DOES NOT WORK.  PROBLEM: MotionSequenceCollection does not update.
            //location.Filter = p => (p as ModelBase) == AddPoint;

            //DOES NOT WORK.  PROBLEM: Source is not instantiated(?) and exmaple from stackoverflow and not sure how that got there in the first place.
            //source.Filter = p => (p as ModelBase).GetType() == "AddPoint";
            //return source;

            return location;
        }
    }

采纳答案by makc

All collections have a default CollectionView. WPF always binds to a view rather than a collection. If you bind directly to a collection, WPF actually binds to the default view for that collection. This default view is shared by all bindings to the collection, which causes all direct bindings to the collection to share the sort, filter, group, and current item characteristics of the one default view.

所有集合都有一个默认的 CollectionView。WPF 始终绑定到视图而不是集合。如果直接绑定到集合,WPF 实际上会绑定到该集合的默认视图。此默认视图由​​集合的所有绑定共享,这导致集合的所有直接绑定共享一个默认视图的排序、过滤器、组和当前项目特征。

try creating CollectionViewSourceand setting its filtering logic like this:

尝试创建CollectionViewSource并设置其过滤逻辑,如下所示:

//create it as static resource and bind your ItemsControl to it
<CollectionViewSource x:Key="csv" Source="{StaticResource MotionSequenceCollection}" 
                  Filter="CollectionViewSource_Filter">
    <CollectionViewSource.GroupDescriptions>
       <PropertyGroupDescription PropertyName="YYY"/>
    </CollectionViewSource.GroupDescriptions>
    <CollectionViewSource.SortDescriptions>
         <scm:SortDescription PropertyName="YYY" Direction="Ascending"/>
    </CollectionViewSource.SortDescriptions>
</CollectionViewSource> 

private void CollectionViewSource_Filter(object sender, FilterEventArgs e)
{
    var t = e.Item as ModelBase;
    if (t != null)

    {
        //use your filtering logic here

    }
}

回答by Nikita B

Filtering by type is easy. This should work:

按类型过滤很容易。这应该有效:

location.Filter = p => p.GetType() == typeof(AddPoint);

Sorting is also quite easy. All you need to do is to implement IComparerand assign it to CustomSortproperty of collection view.

排序也很容易。您需要做的就是实现IComparer并将其分配给CustomSort集合视图的属性。

There is no easy way to remove duplicates tho (not that i am aware of). I suggest you to do it elsewhere. For example, you could distinct your underlying collection.

没有简单的方法可以删除重复项(我不知道)。我建议你在别处做。例如,您可以区分您的基础集合。