2016-10-31 3 views
0

ビューモデルプロパティにバインドされた依存プロパティを持つカスタムコントロールを作成しました。 DataContextのはWPF CustomControlは、ビューモデルに依存プロパティを2つの方法でバインドできません。

public partial class MainWindow 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     DataContext = ViewModel = new ViewModel(); 
    } 

    public ViewModel ViewModel { get; set; } 
} 

の背後にあるコードで設定されて

<wpf1:CustomTextBox StringProperty="{Binding StringValue}" /> 

ビューモデルがこの

public class ViewModel : INotifyPropertyChanged 
{ 
    public string StringValue 
    { 
     get { return m_stringValue; } 
     set 
     { 
      m_stringValue = value; 
      OnPropertyChanged("StringValue"); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected virtual void OnPropertyChanged(string propertyName) 
    { 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
    } 

    private string m_stringValue; 
} 

のように見える依存関係プロパティの結合様式は、デフォルト

ことにより、2つの方法です。
public static readonly DependencyProperty StringPropertyProperty = 
     DependencyProperty.Register(
      "StringProperty", 
      typeof(string), 
      typeof(CustomTextBox), 
      new FrameworkPropertyMetadata 
      { 
       BindsTwoWayByDefault = true, 
       DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged, 
       PropertyChangedCallback = PropertyChangedCallback 
      }); 

今、ビューモデルのプロパティStringValueが変更されたときにカスタムコントロールに通知されますが、依存関係プロパティの値を変更すると、ビューモデルの値は変更されません。

private static void PropertyChangedCallback(DependencyObject dO, 
    DependencyPropertyChangedEventArgs e) 
    { 
     var textBox = (CustomTextBox) dO; 
     if (textBox.StringProperty == null) 
      return; 
     DoSomething(textBox.StringProperty) 
     textBox.StringProperty = null; 
    } 

私はビューのモデルの値を "some value"に設定した場合、カスタムコントロールでその文字列を使用してnullにリセットする必要があります。これまでのところ、これはうまくいきますが、ビューモデルの値は同期化されておらず、nullではなく「一部の値」のままです。どのようにこれを行うにはどのようなアイデア?なぜ、双方向バインディングがそのように機能しないのですか?

ありがとうございました。

+0

O/Tですが、 'public ViewModel ViewModel {get {ViewModelとしてDataContextを返します。 }セット{DataContext =値; }} 'は、型付きのプロパティを' DataContext'と同期させておく心配を省きます。 –

答えて

0

あなたのコードが期待どおりに動作しない理由理由は、「あなたのことですStringPropertyに新しい値を割り当てて、そのプロパティに対する以前の変更を処理します。私はそれの背後にある仕組みを実際には知らない(潜在的に無限の再帰呼び出しを防ぐための何らかのメカニズムかもしれない)が、それは原因で100%に過ぎない。

private static void PropertyChangedCallback(DependencyObject dO, 
    DependencyPropertyChangedEventArgs e) 
{ 
    var textBox = (CustomTextBox) dO; 
    if (textBox.StringProperty == null) 
     return; 
    DoSomething(textBox.StringProperty) 
    //following lambda will be queued for execution rather than executed immediately 
    //and is guaranteed to be executed after this handler has finished 
    textBox.Dispatcher.InvokeAsync(() => textBox.StringProperty = null); 
} 

あなたがしている場合は、次のコントロールが簡単にコントロールに関連付けられたDispatcherを使用することによって達成することができ、あなたのハンドラから返されるまで、新しい値の割り当てを延期するのに十分であるあなたの問題を解決するために

4.5より前の.NETバージョンを使用する場合は、代わりにDispatcher.BeginInvokeメソッドを使用する必要があります。

+0

完璧に動作します!どうもありがとう。 –

2

先に定義された

textBox.StringProperty = null; 

が結合削除この行は(<wpf1:CustomTextBox StringProperty="{Binding StringValue}" />

トライ使用は

textBox.SetCurrentValue(StringPropertyProperty, null); 
+0

ヒントをありがとう。残念ながら、SetCurrentValueが正確に私が探しているものであることをツールチップが示しているにもかかわらず、これはどちらも動作しません(SetValueと同じです)。私が依存プロパティーの代わりにTextpropertyのようなビルドイン・プロパティーで使用すると、それは期待どおりに動作します。 ... –

+0

明らかにするために、 'TwoValue'と' OneWayToSource'バインディングモードのために、 'SetValue'は、ターゲットからソースへのデータ転送がサポートされている場合、プロパティのバインディングセットを削除しません。 – Grx70

関連する問題