2017-06-29 7 views
0

私はDependencyObjectのビューモデルを持っていますが、DependencyPropertyはビューを新しい値で更新していません。DependencyObjectはビューを更新していません

サンプルプロパティは(予想通り取得/設定ラッパーが呼び出されます)

public static readonly DependencyProperty WeaponNameProperty = DependencyProperty.Register(
     "WeaponName", 
     typeof(string), 
     typeof(WeaponSystemVM), 
     new PropertyMetadata(null, new PropertyChangedCallback(OnWeaponNameChanged))); 
    public string WeaponName 
    { 
     get { return (string)GetValue(WeaponNameProperty); } 
     set { SetValue(WeaponNameProperty, value); } 
    } 

CallbackWeaponNameが変更されたときに呼び出される)

private static void OnWeaponNameChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
{ 
    WeaponSystemVM vm = d as WeaponSystemVM; 
    if (vm != null) 
    { vm.CommandAddWeaponSystem.RaiseCanExecuteChanged(); } 
} 

CanExecute Delegate(期待通りに実行します関連するアップデート:Button

private bool CanAddSystem() 
{ 
    if (string.IsNullOrWhiteSpace(WeaponName)) return false; 
    if (string.IsNullOrWhiteSpace(WeaponLock)) return false; 
    if (string.IsNullOrWhiteSpace(WeaponDamage)) return false; 
    if (string.IsNullOrWhiteSpace(WeaponAttack)) return false; 
    return true; 
} 

入力TextBox

<TextBox x:Name="NameInput" Text="{Binding WeaponName, Mode=TwoWay}" Margin="12,4" RelativePanel.Below="NameAdorner" RelativePanel.AlignLeftWithPanel="True" 
        RelativePanel.AlignRightWithPanel="True"/> 

出力TextBlock(新しい値で更新し、DataContextを入力TextBoxと同じではありません)

<TextBlock Text="{Binding WeaponName}"/> 

はイライラ、それだけでこの実装のようですそれは動作していません。
問題を再現するために、私は自分のアプリに関連するすべての追加情報なしで別個のプロジェクトを作成しました。ビューは期待どおりに正確に更新されています。

私が理解していないことは、この実装で正しく行われていないことです。 ViewModelは期待どおりに更新されています。バインディングはLiveVisualTreeに従って有効です。
誰も私に問題を指摘できますか?

+4

なぜ、UIクラスから継承するVMを作成するのかわからない。それは私にとって間違っていると感じます。通常、依存関係のプロパティの代わりにINPCを使用してプロパティを作成します。 – Jessica

答えて

2

ViewModelにはDependencyPropertyを使用しないでください。これはマークアップクラスで、ビュー側のバインディングに使用されます。それはそのように使用されている余裕と範囲外です。
INotifyPropertyChangedを実装し、UIに通知するすべてのプロパティにINotifyPropertyChanged.PropertyChangedイベントを発生させる必要があります。以下のような
何か:

あなたのViewModelは

public abstract class NotifyPropertyChangedBase : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    protected void RaisePropertyChanged([CallerMemberName] string propertyName = null) 
    { 
     this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
    } 

    protected void SetAndRaiseIfChanged<T>(
     ref T backingField, 
     T newValue, 
     [CallerMemberName] string propertyName = null) 
    { 
     if (!object.Equals(backingField, newValue)) 
      return; 

     backingField = newValue; 
     this.RaisePropertyChanged(propertyName); 
    } 
} 

から継承し、あなたのViewModelあなたが

private string _weaponName; 
public string WeaponName 
{ 
    get { return this._weaponName; } 
    set { SetAndRaiseIfChanged(ref this._weaponName, value); } 
} 

のようなより簡潔なCanAddSystemをあなたの財産を定義

private bool CanAddSystem() 
{ 
    return 
     !string.IsNullOrWhiteSpace(WeaponName) 
     && !string.IsNullOrWhiteSpace(WeaponLock) 
     && !string.IsNullOrWhiteSpace(WeaponDamage) 
     && !string.IsNullOrWhiteSpace(WeaponAttack); 
} 

であなたのViewModelのを構築コマンドを使ってICommandインタフェースビュー片が

<TextBlock Text="{Binding WeaponName}"/> 

とあなたが行っているだろう

(RelayCommandのようなもの)を実装:あなたはUIへのICommandをバインドするときに、システムが自動的にCanExecuteからそれを読んで更新しますViewModel。

+0

これまで実際に 'INotifyPropertyChanged'と' RelayCommand'を使用していましたが、これはうまく機能していましたが、プロパティを追跡して更新する手間がかかりました。(上記の基底クラスは私よりもはるかに優れています持ってる)。より自動化されたもののための 'DependencyObject'ルートを試していました。私はまた、システム上のライターを読んでいます。私はその道に沿って続けていくと思います。しかし、更新されていないビューに関する上記の問題は、実際には解決されていません - 問題の内容に関するアドバイスはありますか? – Lindsay

関連する問題