0

我有一个控件列表,其中每个控件都有 ZIndex 属性:

class WizardControl : INotifyPropertyChanged
{
    public int ZIndex { get; set; /* set emits PropertyChanged event */}
}

class WizardStep
{
    ObservableCollection<WizardControl> Controls { get; set; }
}

class Wizard
{
    ObservableCollection<WizardStep> Steps { get; set; }
}

我还有一个TreeViewusing HierarchicalDataTemplate,其中每个WizardStep都有一个树节点,所有节点都WizardControl作为树叶。

现在我想按控件的 ZIndex 对控件进行排序。我找到了一个使用自定义Converter(http://stackoverflow.com/a/5730402/69868)的解决方案,只要 ZIndex 没有改变,它就可以正常工作。

当 ZIndex 更改时,排序后的 CollectionView 不会发出 CollectionChanged 事件,并且 GUI 不会选择顺序更改。

我的问题:如何创建一个排序集合,当由于排序值的变化而重新排序项目时,该集合将发出正确的事件?

4

3 回答 3

0

ObservableCollectionPropertyChange在集合更改时发出通知,而不是在集合内的对象发生更改时发出通知。

如果你想要那种行为,你必须自己添加它。通常我会在CollectionChanged事件中添加它。

public MyViewModel()
{
    MyCollection.CollectionChanged += MyCollection_CollectionChanged;
}

void MyCollection_CollectionChanged(object sender, CollectionChangedEventArgs e)
{
    if (e.NewItems != null)
        foreach(MyItem item in e.NewItems)
            item.PropertyChanged += MyItem_PropertyChanged;

    if (e.OldItems != null)
        foreach(MyItem item in e.OldItems)
            item.PropertyChanged -= MyItem_PropertyChanged;
}

void MyItem_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if (e.PropertyName == "Some Property")
    {
        // Do work
        RaisePropertyChanged("MyCollection");
    }
}

由于您在集合上使用转换器,因此只需为集合引发 PropertyChanged 事件即可重新运行转换器

于 2012-06-19T13:33:50.740 回答
0

为此,您必须使用CollectionView包裹在您的ObservableCollectionwith周围CollectionView.SortDescriptions.Add(new SortDescription(ZIndex))

这样,每当ZIndex可观察集合中的任何项目发生变化时,它都会自动在 GUI 上获取正确的排序位置。

于 2012-06-19T07:36:17.223 回答
0

我想您可以自己在集合中实现 INotifyCollectionChanged 接口,该集合可以侦听 WizardControl 的属性更改事件参数,让您完全控制事情的完成方式。我已经包含了一个如何完成的小样本。

WizardControl.cs

    public class WizardControl : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        int zIndex;
        PropertyChangedEventArgs zIndexArgs = new PropertyChangedEventArgs("ZIndex");

        public int ZIndex
        {
            get { return zIndex; }
            set
            {
                if (zIndex != value)
                {
                    zIndex = value;
                    PropertyChangedEventHandler temp = PropertyChanged;
                    if (temp != null)
                        temp(this, zIndexArgs);
                }
            }
        }

        public override string ToString()
        {
            return zIndex.ToString();      

        }
}

WizardCollection.cs

public class WizardCollection : INotifyCollectionChanged, IEnumerable<WizardControl>
{
    public event NotifyCollectionChangedEventHandler CollectionChanged;
    NotifyCollectionChangedEventArgs collectionChangedMoveArgs = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset);

    List<WizardControl> items = new List<WizardControl>();

    public WizardControl this[int index]
    {
        get { return items[index]; }
    }

    public void Add(WizardControl item)
    {
        if (items == null) items = new List<WizardControl>();
        items.Add(item);
        item.PropertyChanged += new PropertyChangedEventHandler(item_PropertyChanged);
        NotifyCollectionChangedEventHandler temp = CollectionChanged;
        if (temp != null)
            temp(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
    }

    public void Remove(WizardControl item)
    {
        item.PropertyChanged -= new PropertyChangedEventHandler(item_PropertyChanged);
        NotifyCollectionChangedEventHandler temp = CollectionChanged;
        if (temp != null)
            temp(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item));
    }

    void item_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "ZIndex")
        {
            items = items.OrderBy(x => x.ZIndex).ToList();
            NotifyCollectionChangedEventHandler temp = CollectionChanged;
            if (temp != null)
                temp(this, collectionChangedMoveArgs);
        }
    }

    public IEnumerator<WizardControl> GetEnumerator()
    {
        return items.GetEnumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return items.GetEnumerator();
    }
}
于 2012-06-19T07:59:43.780 回答