数据绑定POCO属性

时间:2009-03-02 10:27:49

标签: c# .net data-binding poco system.componentmodel

是否有任何数据绑定框架(BCL或其他)允许实现INotifyPropertyChangedINotifyCollectionChanged的任何两个CLR属性之间的绑定?似乎应该可以这样做:

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

someSourceObjectsomeTargetObject只是实施INotifyPropertyChanged的POCO。但是,我不知道任何BCL对此的支持,并且不确定是否存在允许这样做的现有框架。

更新:鉴于没有现有的库可供使用,我自己编写了自己的库。它可用here

由于

6 个答案:

答案 0 :(得分:10)

我写了Truss来填补空白。

答案 1 :(得分:7)

我不知道有任何这样做 - 但你可以很容易地写自己的。

这是我在几分钟内敲定的基础,它在两个简单的属性之间建立了双向数据绑定:

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

当然,这段代码缺少一些细节。要添加的内容包括

  • 检查是否已分配sourcetarget
  • 检查sourcePropertyNametargetPropertyName标识的属性是否存在
  • 检查两个属性之间的类型兼容性

此外,反射速度相对较慢(虽然在丢弃它之前进行基准测试,但 速度慢),所以您可能希望使用编译后的表达式。

最后,鉴于按字符串指定属性容易出错,您可以使用Linq表达式和扩展方法。然后而不是写

Binder.Bind( source, "Name", target, "Name")
你可以写

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

答案 2 :(得分:1)

AutoMapper可以在两个实例之间复制值,但您必须编写自己的代码才能自动执行此操作。

答案 3 :(得分:1)

也许Bindable LINQcontinuous linq可以提供帮助。如果您尝试添加实际更新数据的实际“派生属性”的模型属性,以便UI更容易绑定,则这两个框架应该有所帮助。

答案 4 :(得分:0)

我写了一个小Bind项目,完全支持neasted属性异步绑定操作之间的绑定。 sintax可以更简单:

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

答案 5 :(得分:-2)

如果您将属性定义为DependencyProperty,则可以执行此操作。 WF和WPF都有它的实现(第一个链接用于WPF。对于WF,它是this一个)所以你需要决定使用哪个 - 但两者都应该满足你的需要。