web-dev-qa-db-ja.com

親プロパティが変更されたときのネストされたプロパティのWPFバインディング更新通知

複雑なプロパティタイプのViewModelがあり、ビューをこのオブジェクトのネストされたプロパティにバインドしたいと考えています。

私のViewModelはINotifyPropertyChangedを実装しています(または正確にはBaseViewModelが実装しています)。親プロパティのクラスはINotifyPropertyChangedを実装していません。

親プロパティの値を更新しているとき、ネストされたプロパティは更新されません。この機能を実装する方法を教えてください。

ViewModel

public class ViewModel : BaseViewModel
{
    private Car _myCarProperty;

    public Car MyCarProperty
    {
        get { return _myCarProperty; }
        set
        {
            if (value == _myCarProperty) return;

            _myCarProperty = value;
            OnPropertyChanged();
        }
    }
}

ビューでのバインド

<TextBlock Text="{Binding Path=MyCarProperty.Manufacturer}" />

MyCarPropertyの値を変更しても、ビューが更新されません。

助けてくれてありがとう!

編集:OnPropertyChanged()の実装

#region INotifyPropertyChanged

public event PropertyChangedEventHandler PropertyChanged;

[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
    PropertyChangedEventHandler handler = PropertyChanged;
    if (handler != null)
    {
        handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

#endregion INotifyPropertyChanged
12
Felix C

「クラスCarはINotifyPropertyChangedを実装していません。しかし、プロパティManufacturerを変更していません。MyCarPropertyプロパティを変更しているので、OnNotifyPropertyChangedイベントが値の更新をトリガーすると思いますか?」

いいえ、レベルダウンの値更新はトリガーされません。バインディングは、パス全体のプロパティの変更をリッスンするのではなく、バインドされているオブジェクトのみをリッスンします。

頭のてっぺんからいくつかのオプションが表示されます(これに遭遇したときの好みの順に):

  1. サブプロパティではなく車にバインドし、必要なものを表示する データテンプレート を作成します。
  2. 必要に応じて、その BindingExpression でUpdateTargetを呼び出して、バインディングを手動でキックします。

データテンプレートルートについて学ぶことはまだまだたくさんあるようですが、データテンプレートが大幅により強力でスケーラブルであることを証明することをお約束します。 WPFでより多くの作業を行うため、手動でバインディングをキックするよりも保守が容易で便利です。 (また、それらを理解すると、手動でバインディングをキックするよりも実際には少ない作業だと思います)。

幸運を!

17
Greg D

受け入れられた回答は、バインディングソースのサブプロパティが変更され、ビューを更新したい場合の処理​​方法を説明しています-これは質問が求めているものではありません。実際、WPFは、指定されたパス内で変更されたプロパティの変更を通知している限り、多くのレベルからの変更に応答します。

これに関して:

「クラスCarはINotifyPropertyChangedを実装していません。しかし、私はプロパティManufacturerを変更していません。MyCarPropertyプロパティを変更しているので、OnNotifyPropertyChangedイベントが値の更新をトリガーすることを期待しています。 ?」

WPFはこれをすでに処理しています。

あなたの例では、ViewModelがバインディングソースです。 MyCarPropertyを設定すると(NotifyPropertyChangedイベントを発生させる)、WPFはnewバインディングのバインディングパスを使用してバインディングターゲット値を再評価しますソースオブジェクト-新しいManufacturerでビューを更新します。

単純なWPFアプリでこれをテストしました。これは、非常に深くネストされたパスにも当てはまります。

https://Pastebin.com/K2Ct4F0F

<!-- When MyViewModel notifies that "MyCarProperty" has changed, -->
<!-- this binding updates the view by traversing the given Path -->
<TextBlock Text="{Binding Path=MyCarProperty.Model.SuperNested[any][thing][you][want][to][try][and][access].Name}" />
5
notracs

私はWPFの専門家ではありませんが、間違ったパスを選択したためだと思います。

<TextBlock Text="{Binding Path=MyCarProperty, Value=Manufacturer}" />

更新:

<TextBlock Text="{Binding Source=MyCarProperty, Path=Manufacturer}" />
3