2012-06-20 8 views
5

¿Es posible establecer el valor detrás de un enlace bidireccional directamente, sin conocer la propiedad enlazada?Establezca el valor de enlace directamente

que tienen una propiedad adjunta que está enlazado a una propiedad como esta:

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

Ahora quieren cambiar el valor que se almacena de manera efectiva en Something desde la perspectiva de la propiedad adjunta. Por lo tanto, no puedo acceder directamente a la propiedad vinculada, pero solo tengo referencias al objeto DependencyObject (es decir, la instancia Element) y al objeto DependencyProperty.

El problema cuando simplemente configurándolo a través de DependencyObject.SetValue es que esto efectivamente elimina el enlace, pero quiero cambiar la propiedad de límite subyacente.

Utilizando BindingOperations puedo obtener el Binding y el BindingExpression. ¿Ahora hay una forma de acceder a la propiedad detrás de ella y cambiar su valor?

+0

¿Usted escribió el documento adjunto-Apoyo a sí mismo como en el que puede cambiar su PropertyMetadata? ¿Supongo que no? –

+0

@HellScream Sí, estoy escribiendo la propiedad yo mismo, así que puedo cambiar los metadatos si eso ayuda. – poke

Respuesta

3

bien, he resuelto esto ahora mismo usando algunos trucos de reflexión sobre la expresión de enlace.

Básicamente, miro la ruta de enlace y el elemento de datos que responde y trato de resolver el enlace por mi cuenta. Esto probablemente fallará para rutas de enlace más complejas, pero para un nombre de propiedad simple como en mi ejemplo anterior, esto debería funcionar bien.

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

no funciona cuando la ruta es compleja. Porque cuando la ruta es algo así como Customer.Name, la propiedad actual no existe en el DataItem de BindingExpression. Es propiedad de otro objeto (en ese caso, por parte del Cliente). –

+0

@KubilayKara Si lee mi respuesta, notará que dije que solo funcionaría para nombres de propiedad simples. Si tiene rutas de enlace complejas, primero deberá analizar la ruta y recorrer los objetos para encontrar la propiedad correcta. – poke

0

¿Qué le parece lanzar el DependencyObjet a Element y establecer la propiedad? ¿Es eso posible?

+0

Como la propiedad es una propiedad adjunta, el tipo Elemento no contiene dicha propiedad en sí. Y 'Something' es parte del contexto de datos al que no tengo acceso directo desde donde deseo cambiar el valor. – poke

0

intente configurar un valor predeterminado en el PropertyMetadata

Puede encontrar más información en MSDN - http://msdn.microsoft.com/en-us/library/system.windows.propertymetadata.aspx

Aquí se muestra un ejemplo:

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

La propiedad ya tiene un valor predeterminado, pero lo que quiero es cambiar el valor * después *. Además, no creo que el valor predeterminado se considere en absoluto cuando el valor de la propiedad adjunta se establece realmente (a un enlace). – poke

0

El problema cuando simplemente establecer que a través de DependencyObject.SetValue es que esto elimina eficazmente la unión, pero quiero cambiar la propiedad subyacente ligado.

Esto es cierto si Binding.Mode está configurado en OneWay. Si está configurado en TwoWay, el uso de DependencyObject.SetValue no eliminará su enlace.

Esta es una cita de Pro WPF 4.5 en C# (página 232):

Extracción de una unión: Si desea eliminar un enlace para que pueda establecer una propiedad de la forma habitual, se necesita la ayuda del método ClearBinding() o ClearAllBindings(). No es suficiente simplemente aplicar un nuevo valor a la propiedad. Si usa un enlace bidireccional, , el valor que establece se propaga al objeto vinculado, y ambas propiedades permanecen sincronizadas.

Entonces, para poder cambiar (y propagar) el my: Utils.MyProperty con SetValue sin eliminar su enlace:

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

Puede pasar el valor a través de un enlace en un objeto ficticio.

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

Ésta es mi objeto ficticio

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