1

リストに基づいたカスタムコレクションを作成しています。その目的は、監視可能、重複防止、ソートなどです。

私は次のような add メソッドを持っています:

    public class SortedObservableCollection<T> : List<T>, INotifyPropertyChanged, INotifyCollectionChanged
    {
        public void Add(T item)
        {
            base.Add(item);
            base.Sort();
            this.OnPropertyChanged("Count");
            this.OnPropertyChanged("Item[]");
            this.OnCollectionChanged(NotifyCollectionChangedAction.Add, item);
        }
}

しかし、どういうわけか、オブジェクトがコレクション内で直接変更された場合、自動手段を実行するか、コレクションに通知して、再度ソートできるようにする必要があります。

お気に入り :

SortedObservableCollection<IRCUser> users = new SortedObservableCollection<IRCUser>();
users.Add(new IRCUser { Nick = "User1", Status = IRCUserStatus.Unknown });
users.Add(new IRCUser { Nick = "User2", Status = IRCUserStatus.Unknown });
users.Add(new IRCUser { Nick = "User3", Status = IRCUserStatus.Unknown });


users.Single(x => x.Nick == "User3").Nick = "User11";

User3 はコレクションの一番下にとどまります。私は独自の IComparable 実装を使用していることに注意してください。これは単なるアルファベット順の並べ替えではありません。

この変更をキャッチして通知するには、コレクションが必要です。これにより、何かを行うことができます。

オブジェクトに INotifyPropertyChanged を実装する必要があることはわかっていますが、コレクションがそれをどのようにキャッチするかについては不明です。

item.PropertyChanged += (o,e) { ..check then... base.Sort(); };

しかし、10,000 人のユーザーがいる場合、これでよいでしょうか?

4

2 に答える 2

0

私が思ったように、コレクション内のすべてのオブジェクトにリスナーを追加し、アイテムが削除されたときにそれを削除することが解決策のようです。私はそれを次のように実装できます:

public class SortedObservableList<T> : List<T>, INotifyPropertyChanged, INotifyCollectionChanged where T : INotifyPropertyChanged, IComparable<T>
{
    public void Add(T item)
    {
        base.Add(item);
        base.Sort();
        this.OnPropertyChanged("Count");
        this.OnPropertyChanged("Item[]");
        this.OnCollectionChanged(NotifyCollectionChangedAction.Add, item);
        item.PropertyChanged += InnerObjectChanged;
    }

    private void InnerObjectChanged(object sender, PropertyChangedEventArgs e)
    {
        base.Sort();
    }

    public bool Remove(T item)
    {
        item.PropertyChanged -= InnerObjectChanged;
        bool result = base.Remove(item);
        this.OnPropertyChanged("Count");
        this.OnPropertyChanged("Item[]");
        this.OnCollectionChanged(NotifyCollectionChangedAction.Remove, item);
        return result;
    }

    protected virtual void OnPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    protected virtual void OnCollectionChanged(NotifyCollectionChangedAction action, object item)
    {
        if (this.CollectionChanged != null)
        {
            this.CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, item));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    public event NotifyCollectionChangedEventHandler CollectionChanged;
}

IRCユーザー

    public class IRCUser : IComparable<IRCUser>, INotifyPropertyChanged
    {
        private string _nick;
        public string Nick
        {
            get
            {
                return _nick;
            }
            set
            {
                if (value != _nick)
                {
                    ...
                    OnPropertyChanged();
                }
            }
        }

        public int CompareTo(IRCUser other)
        {
...
        }


        private void OnPropertyChanged([CallerMemberName] String propertyName = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }

これをテストしたところ、うまくいくようです。

于 2013-07-04T13:09:19.627 に答える