Si crea el enlace en el código de detrás, puede hacer que funcione. Por ejemplo, un simple código generado es vinculante:
Binding binding = new Binding("BindingPath");
binding.Mode = BindingMode.TwoWay;
BindingOperations.SetBinding(textBoxName, TextBox.TextProperty, binding);
Puesto que la trayectoria de esta unión ("BindingPath") es una cadena, esa cadena podría venir de cualquier objeto disponible.
Sin embargo, tendrá que enganchar en la creación de sus elementos de datos para establecer estos enlaces.
Una posibilidad adicional sobre la base de sus comentarios:
This blog post describe una manera de crear una clase personalizada de unión heredando de MarkupExtension. Es posible que pueda utilizar esto como punto de partida para incluir mi sugerencia en un marcado xaml reutilizable para su caso especial de encuadernación.
Más pensamientos:
Bueno, esto fue un problema interesante, así que decidimos pasar un poco de tiempo de ver si podía llegar a una solución de trabajo. Me disculpo de antemano por la longitud de los siguientes ejemplos de código ...
Basando mi solución en el blog he vinculado a lo anterior creado esta clase:
public class IndirectBinder : MarkupExtension
{
public string IndirectProperty { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
//try to get bound items for our custom work
DependencyObject targetObject;
DependencyProperty targetProperty;
bool status = TryGetTargetItems(serviceProvider, out targetObject, out targetProperty);
if (status)
{
Control targetControl = targetObject as Control;
if (targetControl == null) return null;
//Find the object to take the binding from
object dataContext = targetControl.DataContext;
if (dataContext == null) return null;
//Reflect out the indirect property and get the value
PropertyInfo pi = dataContext.GetType().GetProperty(IndirectProperty);
if (pi == null) return null;
string realProperty = pi.GetValue(dataContext, null) as string;
if (realProperty == null) return null;
//Create the binding against the inner property
Binding binding = new Binding(realProperty);
binding.Mode = BindingMode.TwoWay;
BindingOperations.SetBinding(targetObject, targetProperty, binding);
//Return the initial value of the binding
PropertyInfo realPi = dataContext.GetType().GetProperty(realProperty);
if (realPi == null) return null;
return realPi.GetValue(dataContext, null);
}
return null;
}
protected virtual bool TryGetTargetItems(IServiceProvider provider, out DependencyObject target, out DependencyProperty dp)
{
target = null;
dp = null;
if (provider == null) return false;
//create a binding and assign it to the target
IProvideValueTarget service = (IProvideValueTarget)provider.GetService(typeof(IProvideValueTarget));
if (service == null) return false;
//we need dependency objects/properties
target = service.TargetObject as DependencyObject;
dp = service.TargetProperty as DependencyProperty;
return target != null && dp != null;
}
Se puede utilizar esta nueva marcación con el XAML siguiente:
<TextBox Text="{local:IndirectBinder IndirectProperty=FieldValuePath}"/>
Dónde cuadro de texto puede ser cualquier clase que hereda de control y texto puede ser cualquier propiedad de dependencia.
Obviamente si necesita exponer cualquiera de las otras opciones de enlace de datos (como el enlace de una o dos vías), tendrá que agregar más propiedades a la clase.
Si bien esta es una solución complicada, una de las ventajas que tiene sobre el uso de un convertidor es que la vinculación que finalmente se crea va en contra de la propiedad interior real en lugar del objeto. Esto significa que reacciona correctamente a los eventos PropertyChanged.
bien, este es un enfoque que podría funcionar, pero que realmente me gustaría ser capaz de crear enlaces en XAML, porque estoy planeando escribir tienen diferentes propiedades de unión en función del estado de los datos subyacentes. Pero posiblemente i de hecho podría tratar de escribir todo esto lógica en el código subyacente ... – arconaut
y, además, no sólo TextBlock que tengo la intención de especificar unión para. Se supone que es un editor/visor para cualquier propiedad en cualquier objeto. Creo que debería agregarlo a la publicación principal. – arconaut
gracias por la respuesta, y gracias por el enlace. Voy a probar esto – arconaut