WPF Binding filtered ObservableCollection ICollectionView to Combobox

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-06 02:44:50

问题


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.

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

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;
        }
    }

回答1:


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.

try creating CollectionViewSource and setting its filtering logic like this:

//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

    }
}



回答2:


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 IComparer and assign it to CustomSort property of collection view.

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.



来源:https://stackoverflow.com/questions/17387506/wpf-binding-filtered-observablecollection-icollectionview-to-combobox

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!