web-dev-qa-db-ja.com

WPFでの双方向バインディング

WPFで双方向バインドを機能させることができません。

アプリのメインウィンドウに、TextBoxにバインドされている文字列プロパティがあります(モードを "TwoWay"に設定しています)。

TextBoxの値が更新されるのは、ウィンドウが初期化されるときだけです。

TextBoxに入力しても、基になる文字列プロパティの値は変わりません。

文字列プロパティの値が外部ソースによって変更された場合(たとえば、クリック時のイベントで、TextBoxの値をリセットするだけ)、変更はTextBoxに反映されません。

このほとんど取るに足らない例でも、双方向バインディングを正しく動作させるために実装する必要がある手順は何ですか?

29
evizaer

ほとんどの場合、WPF dependencyProperty(他のいくつかのものに加えて変更通知を提供する)ではなく、.net CLRプロパティにバインドしようとしています。
通常のCLRプロパティの場合、INotifyPropertyChangedを実装し、PropertyChangedのイベントハンドラーのテキストボックスを強制的に更新する必要があります。

  • プロパティを持つオブジェクトにこのインターフェイスを実装させ、プロパティセッターでイベントを発生させます。 (これで、プロパティ変更通知があります)
  • オブジェクトがUI要素/コントロールのDataContextプロパティとして設定されていることを確認してください

WPFデータバインディングについて学び始めたときも、これは私を失望させました。

更新:まあ、私は間違ったツリーを吠えていたら時間の無駄だったでしょう..とにかく今少し掘る必要があったので.. この答えを四捨五入するコードスニペットを次に示します。また、タブアウトするとすぐにテキストボックスの更新が自動的に行われることもわかりました。datacontextオブジェクトがINotifyPropertyChangedを実装していない場合は、手動でイベントをサブスクライブしてUIを更新するだけで済みます。

MyWindow.xaml

<Window x:Class="DataBinding.MyWindow" ...
    Title="MyWindow" Height="300" Width="300">
    <StackPanel x:Name="TopLevelContainer">
        <TextBox x:Name="txtValue"  Background="AliceBlue" Text="{Binding Path=MyDotNetProperty}" />
        <TextBlock TextWrapping="Wrap">We're twin blue boxes bound to the same property.</TextBlock>
        <TextBox x:Name="txtValue2"  Background="AliceBlue" Text="{Binding Path=MyDotNetProperty}" />
    </StackPanel>
</Window>

MyWindow.xaml.cs

public partial class MyWindow : Window, INotifyPropertyChanged
{
    public MyWindow()
    {
        InitializeComponent();
        this.MyDotNetProperty = "Go ahead. Change my value.";
        TopLevelContainer.DataContext = this;
    }

    private string m_sValue;
    public string MyDotNetProperty
    {
        get { return m_sValue; }
        set
        {
            m_sValue = value;
            if (null != this.PropertyChanged)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("MyDotNetProperty"));
            }
        }
    }

    #region INotifyPropertyChanged Members
    public event PropertyChangedEventHandler PropertyChanged;
    #endregion
}
59
Gishu

精度を上げる必要があると感じています。

「双方向」データバインディングは、「片方向」データバインディング以上のものです。

「一方向」のデータバインディングは、ソースから依存性プロパティへのバインディングです。ソースからターゲットへの変更の伝播を取得するには、ソースがINotifyProertyChangedを実装する必要があります。

「2方向」を取得し、ターゲットからソースへの伝播を取得するには、Bindingで設定したバインドモードによって異なります。バインディングにBindingModeを設定しない場合、デフォルトのバインディングモードが使用されます。このデフォルトモードは、ターゲットの依存関係プロパティの特性です。

例:

「MyTextProperty」と呼ばれる文字列プロパティにバインドされたテキストボックス。コードでは、Textbox.Text DependencyPropertyをオブジェクト「MyObject」の「MyTextProperty」にバインドします

-> "一方向"バインディング: "My TextProperty"のセッターはイベントProperty Changedを発生させ、 "MyObject"はINotifyPropertyChangedを実装する必要があります。

->「2ウェイデータバインディング」:「1ウェイ」に必要なものに加えて、bindingModeを「2ウェイ」に設定する必要があります。この特別なケースでは、TextboxのText DependencyPropertyにはデフォルトモードとして「2つの方法」があるため、他に行うことはありません。

5
flamandier

コードを見る必要があるかもしれません。文字列プロパティはPropertyChangedイベントを発生させますか?または(さらに良い)DependencyPropertyとして実装されていますか?そうでない場合、バインドされたTextBoxは値がいつ変更されるかを認識しません。

TextBoxに入力してプロパティの値の変更が表示されない場合は、TextBoxがフォーカスを失っていないためと考えられます。既定では、バインドされたTextBoxは、フォーカスがコントロールを離れるまで、値をソースプロパティに書き戻しません。タブを移動して、プロパティ値が変化するかどうかを確認してください。

3
Matt Hamilton