diseñador - herramientas de windows forms c#
Propiedades de enlace de datos POCO (6)
¿Hay algún marco de enlace de datos (BCL o de otro tipo) que permita el enlace entre dos propiedades CLR que implementen INotifyPropertyChanged
y INotifyCollectionChanged
? Parece que debería ser posible hacer algo como esto:
var binding = new Binding();
binding.Source = someSourceObject;
binding.SourcePath = "Customer.Name";
binding.Target = someTargetObject;
binding.TargetPath = "Client.Name";
BindingManager.Bind(binding);
Donde someSourceObject
y someTargetObject
son solo POCOs que implementan INotifyPropertyChanged
. Sin embargo, no tengo conocimiento de ningún soporte de BCL para esto, y no estoy seguro de si hay marcos existentes que lo permitan.
ACTUALIZACIÓN : Dado que no hay una biblioteca disponible, me he comprometido a escribir la mía. Está disponible here .
Gracias
Escribí here para llenar el vacío.
Escribí un pequeño proyecto Bind con soporte completo para el enlace entre propiedades neasted y acciones de enlace asíncronas. La sintaxis no puede ser más sencilla:
//Two way binding between neasted properties:
Bind.TwoWay(()=> client.Area.Data.Name == this.AreaName);
//On change action execute:
Bind
.OnChange(()=> client.Personal.Name)
.Do(x => clientName = x);
No tengo conocimiento de ninguna biblioteca que haga esto, pero usted podría escribir su propia bastante fácilmente.
Aquí hay una base que descubrí en unos minutos que establece un enlace de datos bidireccional entre dos propiedades simples:
public static class Binder
{
public static void Bind(
INotifyPropertyChanged source,
string sourcePropertyName,
INotifyPropertyChanged target,
string targetPropertyName)
{
var sourceProperty
= source.GetType().GetProperty(sourcePropertyName);
var targetProperty
= target.GetType().GetProperty(targetPropertyName);
source.PropertyChanged +=
(s, a) =>
{
var sourceValue = sourceProperty.GetValue(source, null);
var targetValue = targetProperty.GetValue(target, null);
if (!Object.Equals(sourceValue, targetValue))
{
targetProperty.SetValue(target, sourceValue, null);
}
};
target.PropertyChanged +=
(s, a) =>
{
var sourceValue = sourceProperty.GetValue(source, null);
var targetValue = targetProperty.GetValue(target, null);
if (!Object.Equals(sourceValue, targetValue))
{
sourceProperty.SetValue(source, targetValue, null);
}
};
}
}
Por supuesto, este código carece de algunas sutilezas. Las cosas para agregar incluyen
- Comprobando que la
source
y eltarget
están asignados - Comprobando que las propiedades identificadas por
sourcePropertyName
ytargetPropertyName
existen - Comprobando la compatibilidad de tipo entre las dos propiedades
Además, Reflection es relativamente lento (aunque es un punto de referencia antes de descartarlo, no es tan lento), por lo que es posible que desee utilizar expresiones compiladas en su lugar.
Por último, dado que la especificación de propiedades por cadena es propensa a errores, podría usar expresiones Linq y métodos de extensión. Entonces en lugar de escribir
Binder.Bind( source, "Name", target, "Name")
usted podría escribir
source.Bind( Name => target.Name);
Si definieras tus propiedades como DependencyProperty ''s, podrías hacerlo. Tanto WF como WPF tienen una implementación (el primer enlace es para WPF. Para WF es this ), por lo que debe decidir cuál usar, pero ambos deberían ser suficientes para sus necesidades.
Tal vez Bindable LINQ o Linq continuo pueden ayudar aquí. Si está intentando agregar propiedades de modelo que en realidad son "propiedades derivadas" de sus datos reales y actualizados, para facilitar el enlace de la interfaz de usuario, estos dos marcos deberían ayudar.
AutoMapper puede copiar valores entre dos instancias, pero debe escribir su propio código para que esto suceda automáticamente.