2009-03-02 14 views
17

¿Existen marcos de enlace de datos (BCL u otros) que permitan la vinculación entre dos propiedades CLR que implementen INotifyPropertyChanged y INotifyCollectionChanged? Parece ser que debería ser posible hacer algo como esto:Enlace de datos Propiedades de POCO

var binding = new Binding(); 
binding.Source = someSourceObject; 
binding.SourcePath = "Customer.Name"; 
binding.Target = someTargetObject; 
binding.TargetPath = "Client.Name"; 
BindingManager.Bind(binding); 

Dónde someSourceObject y someTargetObject son sólo POCOs que implementan INotifyPropertyChanged. Sin embargo, no conozco ningún soporte de BCL para esto, y no estoy seguro si existen marcos existentes que lo permitan.

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

Gracias

Respuesta

10

Escribí Truss para llenar el vacío.

1

AutoMapper pueden copiar los valores entre dos instancias, pero usted tiene que escribir su propio código para que esto suceda de forma automática.

1

Tal vez Bindable LINQ o continuous linq pueden ayudar aquí. Si intenta agregar propiedades de modelo que en realidad son "propiedades derivadas" de sus datos actuales y de actualización, para que sea más fácil para su UI vincularse, estos dos marcos deberían ayudar.

7

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

Aquí está una base Toqué en unos pocos minutos que establece la unión entre dos propiedades simples datos de dos vías:

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 le falta un par de sutilezas. Cosas que añadir incluyen

  • Comprobación de que source y target se asignan
  • Comprobación de que las propiedades identificadas por sourcePropertyName y targetPropertyName existen
  • Comprobación de la compatibilidad tipo entre las dos propiedades

También, Reflejo es relativamente lento (aunque lo compara antes de descartarlo, no es que lento), por lo que es posible que desee utilizar compilado expresiones 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 en su lugar. Entonces, en lugar de escribir

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

se podría escribir

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

En realidad, lo estaba preguntando porque estaba considerando escribir el mío. No quería reinventar la rueda y todo ... gracias. –

+0

Actualización: he vinculado a mi biblioteca en la pregunta. –

+0

Necesitaba una clase simple de enlace de datos barebone para mi proyecto actual en prisa, y el anterior casi se ajusta a lo que necesito. Acabo de reemplazar los nombres de propiedad usados ​​con Reflection por dos delegados de Acción en los que obtengo/configuro desde POCO y aplico transformaciones y formateo. Definitivamente le daré una buena oportunidad a Truss en un próximo proyecto, porque realmente me resulta interesante. – Larry

-2

Si ha definido sus propiedades como DependencyProperty 's que podría 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.

+2

DependencyProperty implica heredar de DependencyObject, que no es un POCO. –

+1

+1. En otras palabras, "No se puede con los de poco, solo DP". – Will

+0

¿Eh? No estoy seguro de cuál es su lógica para votar esto. Will. Ninguna sugerencia será suficiente para mis necesidades ya que ninguna de las sugerencias involucra a las POCO. Otra publicación ya ha demostrado que puedes hacerlo con POCO: solo estoy pidiendo un marco que haga el trabajo duro. –

0

Escribí un pequeño proyecto de Bind con soporte completo para vincular entre propiedades neted async acciones de enlace. El sintax no puede ser más sencillo:

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