.net 数据绑定POCO属性

ijxebb2r  于 2023-06-25  发布在  .NET
关注(0)|答案(6)|浏览(129)

是否有任何数据绑定框架(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

谢谢

yqhsw0fo

yqhsw0fo1#

我写了Truss来填补空白。

q0qdq0h2

q0qdq0h22#

我不知道有什么库可以做到这一点--但你可以很容易地编写自己的库。
下面是我在几分钟内想出的一个基础,它在两个简单属性之间建立了双向数据绑定:

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

e1xvtsh33#

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

sg3maiej

sg3maiej4#

AutoMapper可以在两个示例之间复制值,但您必须编写自己的代码才能使其自动发生。

ss2ws0br

ss2ws0br5#

我写了一个小的Bind项目,它完全支持嵌套属性之间的绑定异步绑定操作。Sinax不能再简单了:

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

vfhzx4xs6#

如果你把你的属性定义为DependencyProperty,你就可以这样做。WF和WPF都有它的实现(第一个链接是WPF的。对于WF,它是this一个),所以你需要决定使用哪一个-但这两个都应该足以满足你的需要。

相关问题