Pregunta

¿Existen marcos de enlace de datos (BCL o de otro tipo) que permitan el enlace entre dos propiedades CLR que implementen INotifyPropertyChanged y INotifyCollectionChanged ? Parece ser 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 POCO que implementan INotifyPropertyChanged . Sin embargo, no conozco ningún soporte de BCL para esto, y no estoy seguro si hay marcos existentes que lo permitan.

ACTUALIZACIÓN : dado que no hay una biblioteca existente disponible, me he encargado de escribir la mía. Está disponible aquí .

Gracias

¿Fue útil?

Solución

Escribí Truss para llenar el vacío.

Otros consejos

No conozco ninguna biblioteca que haga esto, pero podría escribir la suya con bastante facilidad.

Aquí hay una base que descubrí en unos minutos que establece el 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 fuente y target están asignados
  • Comprobando que las propiedades identificadas por sourcePropertyName y targetPropertyName existen
  • Comprobando la compatibilidad de tipos entre las dos propiedades

Además, Reflection es relativamente lento (aunque lo compara antes de descartarlo, no es que 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, puede usar expresiones Linq y métodos de extensión en su lugar. Entonces en lugar de escribir

Binder.Bind( source, "Name", target, "Name")

podrías escribir

source.Bind( Name => target.Name);

AutoMapper puede copiar valores entre dos instancias, pero debe escribir su propio código para hacerlo. suceder automáticamente.

Quizás LINdable LINQ o cont. linq puede ayudar aquí. Si está intentando agregar propiedades de modelo que en realidad son "propiedades derivadas" de sus datos actuales y actualizados, para facilitar la vinculación de su UI, estos dos marcos deberían ayudar.

Escribí un pequeño proyecto Bind con soporte completo para el enlace entre propiedades neas y acciones de enlace asíncrono. El sintax no puede ser más simple:

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

Si definió sus 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 one) por lo que debe decidir cuál usar, pero ambos deberían ser suficientes para sus necesidades.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top