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

また、TreeViewusingHierarchicalDataTemplateがあり、それぞれWizardStepにツリーノードがあり、すべてWizardControlがツリーリーフになっています。

次に、コントロールをZIndexで並べ替えます。カスタムConverter(http://stackoverflow.com/a/5730402/69868)を使用した解決策を見つけました。これは、ZIndexが変更されない限り正常に機能します。

ZIndexが変更されると、ソートされたCollectionViewはCollectionChangedイベントを発行せず、GUIは順序の変更を選択しません。

私の質問:並べ替えの値が変更されたためにアイテムが並べ替えられたときに正しいイベントを発行する並べ替えられたコレクションを作成するにはどうすればよいですか?

4

3 に答える 3

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 に答える
0

このためには、でラップアラウンドを使用する必要がありCollectionViewます。ObservableCollectionCollectionView.SortDescriptions.Add(new SortDescription(ZIndex))

このようZIndexにして、監視可能なコレクション内のアイテムが変更されるたびに、GUI上の正しいソート位置が自動的に取得されます。

于 2012-06-19T07:36:17.223 に答える
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");
    }
}

コレクションでConverterを使用しているため、コレクションのPropertyChangedイベントを発生させるだけで、コンバーターを再実行できます。

于 2012-06-19T13:33:50.740 に答える