2016-10-24 11 views
0

私は依存関係のプロパティに関する多くの質問があることを知っていますが、私はそれらの多くを見てきましたが、どれも問題を解決していないようです。プロパティに双方向バインディングを実装する方法は?

<Window x:Class="WpfBindingTest.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:WpfBindingTest" 
     mc:Ignorable="d" 
     Title="MainWindow" Height="350" Width="525" 
     DataContext="{Binding RelativeSource={RelativeSource Self}}"> 
    <StackPanel> 
     <local:TextInputWrapper MyText="{Binding MyTextValue, Mode=TwoWay}" /> 
     <TextBox Text="{Binding MyTextValue, Mode=TwoWay}"/> 
    </StackPanel> 
</Window> 

MyTextValueが変更されたときに通知単なる文字列プロパティです:

private string _myTextValue = "Totally different value"; 
    public string MyTextValue { get { return _myTextValue; } set { _myTextValue = value; OnPropertyChanged(); } } 
    public event PropertyChangedEventHandler PropertyChanged; 

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

TextInputWrapperもかなり単純です:

は、私はこのようなウィンドウを持って

<UserControl x:Class="WpfBindingTest.TextInputWrapper" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:WpfBindingTest" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300" 
      DataContext="{Binding RelativeSource={RelativeSource Self}}"> 
    <TextBox Text="{Binding MyText}"></TextBox> 
</UserControl> 

コードビハインド:

public partial class TextInputWrapper : UserControl 
{ 
    public static readonly DependencyProperty MyTextProperty = DependencyProperty.Register("MyText", 
     typeof(string), typeof(TextInputWrapper), new PropertyMetadata("Empty")); 
    public TextInputWrapper() 
    { 
     InitializeComponent(); 
    } 
    public string MyText 
    { 
     get { return (string)GetValue(MyTextProperty); } 
     set { SetValue(MyTextProperty, value); } 
    } 

} 

私の知る限りでは、私のウィンドウは2つのTextBoxコントロールを持ち、それぞれにバインドされています。 1つの値を変更する場合と同様に、もう1つは更新する必要があります。

しかし、私は2つの別々のテキストボックスで終わります。最初のテキストボックスは "Empty"というテキストで始まり、次のテキストボックスには "全く異なる値"のテキストがあります。このように: Screenshot

そして、いずれかのテキストを変更すると、もう一方のテキストは変更されません。

"完全に異なる値"のテキストで始まり、その値と同期することが期待されます(MainWindowのMyTextValueプロパティへの変更を伝播することで変更を通知することによって変更が伝播します)他のテキストボックスまで)。自分のコントロールでデータバインディングを正しく実装するために欠けているものは何ですか?

+0

UserControlでは、{バインディングMyText、RelativeSource = {RelativeSource AncestoyType = UserControl}} '、およびUserControlのDataContextをSelfにバインドしません。あなたはそれを持っているので、ビューモデルにバインドすることはできません。 –

答えて

2

UserControlのXAMLから割り当て

DataContext="{Binding RelativeSource={RelativeSource Self}}" 

を削除します。代わりに、設定された「内部」コントロールインスタンスへの結合のRelativeSource

<UserControl x:Class="WpfBindingTest.TextInputWrapper" ...> 
    <TextBox Text="{Binding MyText, 
        RelativeSource={RelativeSource AncestorType=UserControl}}"/> 
</UserControl> 

明示的にユーザーコントロールのDataContextのは、すなわち

<local:TextInputWrapper MyText="{Binding MyTextValue, Mode=TwoWay}" /> 
様結合、親コントロールからのDataContextを継承しないように設定します

は、現在のDataContextではなく、ソースオブジェクトとしてUserControlを使用します。

一般的なルールとして

決しては、明示的にユーザーコントロールのDataContextのセット。

+0

それは本当にトリックを行うように見えた。ありがとうございました!どこでも私はこれを読むことができますか?具体的にはRelativeSource部分。 – Inrego

+0

MSDNの[データバインディングの概要](https://msdn.microsoft.com/en-us/library/ms752347(v = vs.110).aspx)の記事は、あなたに良いスタートを与えるはずです。 – Clemens

0

は、この行を変更してみてください:

これに
public static readonly DependencyProperty MyTextProperty = DependencyProperty.Register("MyText", 
typeof(string), typeof(TextInputWrapper), new PropertyMetadata("Empty")); 

public static readonly DependencyProperty MyTextProperty = DependencyProperty.Register("MyText", 
    typeof(string), typeof(TextInputWrapper), new FrameworkPropertyMetadata("Empty", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)); 
+0

'MyText =" {MyTextValue、Mode = TwoWayをバインドしています "" ' – Clemens

+0

いいえ、私は実際にはしませんでした。それでも、デフォルトのバインディング動作をオーバーライドするのは便利です(これは問題ではありませんでしたが)。 – WBuck

関連する問題