Ligação de dados Propriedades POCO
-
03-07-2019 - |
Pergunta
Existem estruturas de dados de ligação (BCL ou não) que permitem a ligação entre o quaisquer duas propriedades CLR que implementar INotifyPropertyChanged
e INotifyCollectionChanged
? Parece ser, deveria ser possível fazer algo parecido com isto:
var binding = new Binding();
binding.Source = someSourceObject;
binding.SourcePath = "Customer.Name";
binding.Target = someTargetObject;
binding.TargetPath = "Client.Name";
BindingManager.Bind(binding);
Onde someSourceObject
e someTargetObject
são apenas POCOs que implementam INotifyPropertyChanged
. No entanto, não tenho conhecimento de qualquer apoio BCL para isso, e não tenho certeza se há quadros existentes que permitem isso.
Atualizar : Dado que não há existente biblioteca disponível, eu ter tomado ele próprio sobre a escrever a minha própria. Ele está disponível aqui .
Graças
Solução
Eu escrevi Truss para preencher o vazio.
Outras dicas
Eu não estou ciente de qualquer biblioteca que faz isso -. Mas você pode escrever seu próprio facilmente
Aqui está uma base Bati-se em poucos minutos, que estabelece dois dados forma vinculativa entre duas propriedades 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);
}
};
}
}
Claro que, este código carece de algumas sutilezas. Coisas para adicionar incluem
- Verificar se
source
etarget
são atribuídos - Verificar se as propriedades identificadas pelo
sourcePropertyName
e existtargetPropertyName
- Verificação de compatibilidade de tipo entre as duas propriedades
Além disso, a reflexão é relativamente lento (embora de referência antes de descartá-lo, não é que lento), de modo que você pode querer usar expressões compiladas em seu lugar.
Por último, dado que especificar propriedades por corda é propenso a erros, você poderia usar expressões LINQ e os métodos de extensão em vez. Então, em vez de escrever
Binder.Bind( source, "Name", target, "Name")
Você poderia escrever
source.Bind( Name => target.Name);
AutoMapper pode copiar valores entre duas instâncias, mas você tem que escrever o seu próprio código para fazer esta acontecer automaticamente.
Bindable LINQ ou contínua linq pode ajudar aqui. Se você está tentando adicionar Propriedades modelo que são realmente do seu actual "propriedades derivadas", atualização de dados, para tornar mais fácil para você UI para vincular a, estes dois quadros devem ajudar.
Eu escrevi um pequeno Bind projeto com suporte completo para a ligação entre as propriedades neasted assíncronos acções de ligação. A sintaxe não pode ser mais simples:
//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);
Se você definiu suas propriedades como DependencyProperty 's que você poderia fazê-lo. Ambos WF e WPF tem uma implementação do mesmo (primeiro link é para WPF. Para WF é esta ), de modo que você precisa decidir qual usar -. mas ambos devem ser suficientes para suas necessidades