2012-06-20 16 views
5

Ist es möglich, den Wert hinter einer bidirektionalen Bindung direkt festzulegen, ohne die gebundene Eigenschaft zu kennen?Setzen Sie den Bindungswert direkt

Ich habe eine angefügte Eigenschaft, die auf eine Eigenschaft wie folgt gebunden ist:

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

Jetzt möchte ich den Wert ändern, die effektiv in Something aus der Perspektive der angefügten Eigenschaft gespeichert ist. So kann ich nicht direkt auf die gebundene Eigenschaft zugreifen, sondern habe nur Referenzen auf die DependencyObject (d. H. Die Element-Instanz) und das DependencyProperty Objekt selbst.

Das Problem, wenn Sie einfach über DependencyObject.SetValue setzen ist, dass dies effektiv die Bindung entfernt, aber ich möchte die zugrunde liegende gebundene Eigenschaft ändern.

Mit BindingOperations kann ich sowohl die Binding als auch die BindingExpression bekommen. Gibt es nun eine Möglichkeit, auf die Eigenschaft dahinter zuzugreifen und ihren Wert zu ändern?

+0

Haben Sie schrieb die Angebrachtes-prop sich wie in können Sie seine PropertyMetadata ändern? Ich denke nicht? –

+0

@HellScream Ja, ich schreibe die Eigenschaft selbst, damit ich die Metadaten ändern kann, wenn das hilft. – poke

Antwort

3

Okay, ich das jetzt selbst gelöst haben mit ein paar Reflektionstricks auf den Bindungsausdruck.

Ich sehe im Grunde den Bindungsweg und die antwortenden Daten und versuchen, die Bindung selbst aufzulösen. Dies wird wahrscheinlich bei komplexeren Bindungspfaden fehlschlagen, aber für einen einfachen Eigenschaftsnamen wie in meinem obigen Beispiel sollte dies gut funktionieren.

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

es funktioniert nicht, wenn der Pfad komplex ist. Da, wenn Pfad wie Customer.Name ist, die tatsächliche Eigenschaft nicht in DataTtem von BindingExpression vorhanden ist. Es gehört einem anderen Objekt (in diesem Fall vom Kunden). –

+0

@KubilayKara Wenn Sie meine Antwort lesen, werden Sie bemerken, dass ich sagte, dass es nur für einfache Eigenschaftsnamen funktioniert. Wenn Sie über komplexe Bindungspfade verfügen, müssen Sie zuerst den Pfad analysieren und die Objekte durchsuchen, um die richtige Eigenschaft zu finden. – poke

0

Wie wäre es, den DependencyObjet auf Element zu übertragen und die Eigenschaft festzulegen? Ist das möglich?

+0

Da es sich bei der Eigenschaft um eine angefügte Eigenschaft handelt, enthält der Elementtyp selbst keine solche Eigenschaft. Und etwas ist Teil des Datenkontexts, auf den ich keinen direkten Zugriff habe, von dem aus ich den Wert ändern möchte. – poke

0

Versuchen Sie, einen Standardwert in der PropertyMetadata

Einstellung können Sie weitere Informationen über MSDN - http://msdn.microsoft.com/en-us/library/system.windows.propertymetadata.aspx

Hier ist ein Beispiel:

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

Die Eigenschaft hat bereits einen Standardwert, aber ich möchte den Wert * nachher * ändern. Auch glaube ich nicht, dass der Standardwert überhaupt berücksichtigt wird, wenn der Wert der angefügten Eigenschaft tatsächlich festgelegt ist (zu einer Bindung). – poke

0

Das Problem, wenn sie einfach über DependencyObject.SetValue Einstellung ist , dass diese wirksam die Bindung entfernt, aber ich mag die zugrunde liegenden gebundene Eigenschaft ändern.

Das ist wahr, wenn der Binding.Mode auf OneWay festgelegt ist. Wenn es auf TwoWay festgelegt ist, wird das Verwenden von DependencyObject.SetValue seine Bindung nicht entfernen.

Dies ist ein Zitat von Pro WPF 4.5 in C# (Seite 232):

Entfernen einer Bindung: Wenn Sie ein verbindliches entfernen möchten, so dass Sie eine Eigenschaft in der üblichen Art und Weise eingestellt, Sie brauche die Hilfe der ClearBinding() oder ClearAllBindings() Methode. Es genügt nicht, einfach einen neuen Wert auf die Eigenschaft anzuwenden. Wenn Sie eine bidirektionale Bindung verwenden, wird der von Ihnen festgelegte Wert an das verknüpfte Objekt weitergegeben und beide -Eigenschaften bleiben synchronisiert.

So in der Lage zu ändern (und propagieren) die my: Utils.MyProperty mit SetValue, ohne seine Bindung zu entfernen:

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

Sie können den Wert über eine Bindung an ein Dummy-Objekt übergeben.

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); 
    } 

Das ist mein Dummy-Objekt

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)); 
}