2012-06-20 9 views
5

バインドされたプロパティを知らなくても、双方向バインディングの背後にある値を直接設定することはできますか?バインディング値を直接設定する

私はこのようなプロパティにバインドされている添付プロパティがあります。今、私は効果的に添付プロパティの視点からSomethingに格納されている値を変更したい

<Element my:Utils.MyProperty="{Binding Something}" /> 

を。したがって、バインドされたプロパティに直接アクセスすることはできませんが、DependencyObject(Elementインスタンス)とDependencyPropertyオブジェクト自体への参照のみがあります。

単純にDependencyObject.SetValueで設定するときの問題は、これが効果的にバインディングを削除するということですが、基本的なバインドされたプロパティを変更する必要があります。

BindingOperationsを使用すると、BindingBindingExpressionの両方を取得できます。今、その背後にあるプロパティにアクセスして価値を変更する方法はありますか?

+0

あなたは付属のプロップあなたはそのPropertyMetadataを変えることができるのように自分自身を書いていましたか?私はないと思いますか? –

+0

@HellScreamはい、私はプロパティを自分で作成しています。そのためにメタデータを変更できます。 – poke

答えて

3

さて、私は今、自分自身を、これを解決しましたバインディング式にいくつかのリフレクトトリックを使用します。

私は基本的にバインディングパスと応答するデータ項目を見て、自分自身でバインドを解決しようとします。これはおそらく、より複雑なバインディングパスでは失敗しますが、上の例のような単純なプロパティ名ではうまくいくはずです。

BindingExpression bindingExpression = BindingOperations.GetBindingExpression(dependencyObj, dependencyProperty); 
if (bindingExpression != null) 
{ 
    PropertyInfo property = bindingExpression.DataItem.GetType().GetProperty(bindingExpression.ParentBinding.Path.Path); 
    if (property != null) 
     property.SetValue(bindingExpression.DataItem, newValue, null); 
} 
+0

パスが複雑な場合は機能しません。 パスがCustomer.Nameのようなものなので、実際のプロパティはBindingExpressionのDataItemに存在しません。 他のオブジェクト(この場合は得意先)が所有します。 –

+0

@ KubilayKaraあなたが私の答えを読んでいるなら、あなたはそれが単純なプロパティ名に対してしか働かないと言いました。複雑なバインディングパスがある場合は、最初にパスを解析し、オブジェクトをトラバースして正しいプロパティを見つける必要があります。 – poke

0

DependencyObjetをElementにキャストしてプロパティを設定する方法はありますか?それは可能ですか?

+0

プロパティは添付プロパティであるため、Elementタイプにはそのようなプロパティ自体は含まれません。そして、「何か」は私が値を変更したい場所から直接アクセスすることができないデータコンテキストの一部です。 – poke

0

あなたはMSDNの詳細情報を見つけることができPropertyMetadata

にデフォルト値を設定してみてください - http://msdn.microsoft.com/en-us/library/system.windows.propertymetadata.aspx

ここでは一例です:

public Boolean State 
    { 
    get { return (Boolean)this.GetValue(StateProperty); } 
    set { this.SetValue(StateProperty, value); } 
    } 
    public static readonly DependencyProperty StateProperty = DependencyProperty.Register(
    "State", typeof(Boolean), typeof(MyStateControl),new PropertyMetadata(myDefaultValue)); 
+0

プロパティにはすでに既定値がありますが、値の変更は後で*できます。また、私は、接続プロパティの値が実際に(バインディングに)設定されているときに、デフォルト値がまったく考慮されていないと考えています。 – poke

0

問題単にDependencyObject.SetValue経由でこの設定が有効にバインディングを削除すること ですが、私はバウンドプロパティの基礎となる を変更したいです。

これは、Binding.ModeがOneWayに設定されている場合に当てはまります。 TwoWayに設定されている場合、DependencyObject.SetValueを使用してもバインディングは削除されません。

これは、C#でプロWPF 4.5からの引用(ページ232)である:あなたが 、通常の方法であなたをプロパティを設定することができるようにバインディングを削除する場合:

バインディングを削除します ClearBinding()またはClearAllBindings()メソッドの助けが必要です。 プロパティに新しい値を適用するだけでは不十分です。双方向バインディングを使用している場合は、 設定した値がリンクされたオブジェクトに伝播され、 のプロパティは同期したままになります。

したがって、my:Utilsを変更(および伝播)できるようにする。バインディングを削除せずにSetValueを使用したMyProperty:

<Element my:Utils.MyProperty="{Binding Something, Mode=TwoWay}" /> 
0

ダミーオブジェクトのバインドを介して値を渡すことができます。

public static void SetValue(BindingExpression exp, object value) 
    { 
     if (exp == null) 
      throw new ValueCannotBeNullException(() => exp); 
     Binding dummyBinding = new Binding(exp.ParentBinding.Path.Path); 
     dummyBinding.Mode = BindingMode.OneWayToSource; 
     dummyBinding.Source = exp.DataItem; 
     SetValue(dummyBinding, value); 
    } 

    public static void SetValue(Binding binding, object value) 
    { 
     BindingDummyObject o = new BindingDummyObject(); 
     BindingOperations.SetBinding(o, BindingDummyObject.ValueProperty, binding); 
     o.Value = value; 
     BindingOperations.ClearBinding(o, BindingDummyObject.ValueProperty); 
    } 

これは私のダミーのオブジェクトである

internal class BindingDummyObject : DependencyObject 
{ 
    public object Value 
    { 
     get 
     { 
      return (object)GetValue(ValueProperty); 
     } 
     set 
     { 
      SetValue(ValueProperty, value); 
     } 
    } 

    public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(object), typeof(BindingDummyObject)); 
}