11

ObservableCollectionサブクラス化してプロパティを追加したいと思います。残念ながら、PropertyChangedイベントは保護されています。SelectedItem基本的に、MVVMWPFアプリのリストにバインドできるようにサブクラス化したいと思います。

これが私のクラスのスケルトンです:

public class SelectableList<T> : ObservableCollection<T>
{
    public T SelectedItem {get;set;}
}

しかし、私は次のことを行うことはできません。

SelectableList<int> intList = new SelectableList<int>();
intList.PropertyChanged += new PropertyChangedEventHandler(intList_Changed);

アクセス制限のため。これにより、私はより深い質問をするようになります。UIはPropertyChangedイベント(カウントプロパティなど)をどのように通知されますか?コードビハインドでは実行できないことに注意してください。

私の頭は回転しています、誰かが私を教えてくれませんか?

4

4 に答える 4

14
SelectableList<int> intList = new SelectableList<int>();
((INotifyPropertyChanged)intList).PropertyChanged += 
    new PropertyChangedEventHandler(intList_Changed);

ObservableCollectionは INotifyPropertyChanged を明示的に実装します。これは、インターフェイスのメソッド、プロパティ、およびイベントにアクセスする前に、インスタンスをインターフェイスにキャストする必要があることを意味します。なぜこれが行われるのか、私にはわかりません。Binding マークアップ拡張機能は、ObservableCollection やその他の型を「認識」しません。型をチェックして、特定のインターフェイス/基本クラス (INPC、INCC、DependencyObject など) を実装または拡張するかどうかを確認するため、インターフェイスが明示的に実装されているかどうかは気にしません。

于 2009-06-16T19:14:47.530 に答える
11

ObservableCollection (int .NET 3.5) は、PropertyChanged イベントを興味深い方法で実装しているようです。

protected event PropertyChangedEventHandler PropertyChanged;

event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged;

これは、保護されたPropertyChangedイベントが内部実装にのみ使用される可能性が高いことを意味します。もう1 つのINotifyPropertyChanged.PropertyChangedイベントは、明示的なインターフェイスとしてINotifyPropertyChangedインターフェイスの実装を実際に実行するイベントです。奇妙なことに、ObservableCollection 内にINotifyPropertyChanged.PropertyChangedが実際に発生する場所がありません。これは、これが .NET 3.5 のバグであることを示している可能性がありますが、たとえば、項目がコレクションに追加されたときに Count のプロパティ変更イベントが発生するかどうかを確認するためにテストしていませんが、それがどのように機能するかを示しています.

.NET 4.0 の実装では、INotifyPropertyChanged.PropertyChangedイベントが、保護されたPropertyChangedイベントによって使用される同じプライベート デリゲートにフックされているように見えますが、これはバグ修正である可能性があります。これは、自動イベントの実装が .NET 4.0 で処理される方法の違いが原因である可能性もあります。

訂正: INotifyPropertyChanged.PropertyChangedイベントが ObservableCollection によって発生することを確認したので、Reflector を使用して ObservableCollection の実装を調べた結果に基づいて上記で行った仮定は不正確でなければなりません。私の推測では、リフレクターが何か奇妙なバグを起こしているのではないかと思います。その証拠はまだありません。

したがって、例を機能させるには、これが機能するように記述する必要があります。Will が回答で示したように、以下の例のようになります。

SelectableList<int> intList = new SelectableList<int>();
((INotifyPropertyChanged)intList).PropertyChanged += 
    new PropertyChangedEventHandler(intList_Changed);

面白いですよね?明示的なインターフェイスの使用は、主に、特定のインターフェイスに必要なメンバーで避けられない衝突を回避するために使用されますが、ある意味でメンバーの存在を隠すために使用できます。

サブクラスに導入する独自のカスタム プロパティのプロパティ変更イベントを発生させたい場合は、ObservableCollection も実装する保護されたOnPropertyChangedメソッドをオーバーライドおよび/または呼び出すことを検討してください。この手法はよく採用されている標準であり、サブクラスは、基になるイベント デリゲートにアクセスせずにイベントを発生させたり、イベントを処理したりできます。ちなみに、一般的には、サブクラスがイベント ハンドラーを独自の基本クラス イベントにフックする代わりに、この手法も使用することをお勧めします。その他の例については、さまざまなコントロールのイベントが WinForms と WPF でどのように実装されているかを見てください。

于 2011-03-29T20:59:41.897 に答える
1

新しいプロパティを追加しようとしました

public class ResultCollection<T> : ObservableCollection<T>
{

        Boolean _val;
        public Boolean Val
        {   
            get
            {   
                return _val;
            }
            set
            {   
                _val= value;
                OnPropertyChanged(new PropertyChangedEventArgs("Val"));
            }
        }
}

PropertyChangedがprotectedとして定義されていることに本当に気づきませんでした。最後に、Val プロパティを ViewModel に移動しました。

于 2012-12-28T06:23:01.880 に答える
0

UI は通知を受け取ることができます。これは、PropertyChanged イベントを保護されたものとして定義する ObservableCollection だけ制限です。

FWIW、ObservableCollection をそのままにして、別のプロパティを VM に追加する方がよいと思います。

于 2009-06-16T19:16:05.763 に答える