数据绑定到对象内由附加到绑定对象的扩展方法返回的属性

本文关键字:对象 扩展 方法 属性 返回 数据绑定 绑定 | 更新日期: 2023-09-27 18:34:38

不确定我是否正确地使用了白话,所以希望代码示例能够澄清。

public class myClassObj
{
    public string aProperty {get;}
}
public class anotherClassObj
{
    public string bProperty {get;}
}

然后我有一个静态扩展方法:

public static anotherClassObj getOtherObj(this myClassObj obj)
{
    anotherClassObj returnObj = new anotherClassObj();
    return returnObj;
}

然后在 XAML 中:

<DataTemplate>
    <TextBlock Text="{Binding aProperty}"/>
    <TextBlock Text="{Binding getOtherObj().bProperty}"/>
</DataTemplate>

忽略明显的语法错误和缺乏构造函数之类的,这样的想法可能吗?

基本上,我想扩展绑定对象以公开比要绑定的实际对象的一部分更多的属性。

数据绑定到对象内由附加到绑定对象的扩展方法返回的属性

这样的想法可能吗?

这个想法?是的。您要求的确切机制是什么?不。

WPF 的 XAML 绑定语法需要源对象的属性路径。扩展方法是编译时构造。在运行时,它只是对静态方法的调用,与传递给该方法的类完全不同的类。绑定系统没有实用的方法来有效地查找扩展方法。

恕我直言,最好的选择是使用"装饰器模式"或类似技术将原始模型对象包装在模型对象中,该对象将扩展方法公开为属性,然后绑定到修饰对象。 例如:

public class myClassObj
{
    public string aProperty {get;}
}
public class DecoratedClassObj : myClassObj
{
    public anotherClassObj OtherObj { get { return this.getOtherObj(); } }
}

然后。。。

<DataTemplate>
    <TextBlock Text="{Binding aProperty}"/>
    <TextBlock Text="{Binding OtherObj}"/>
</DataTemplate>

当然,您的模型对象必须实例化为DecoratedClassObj而不是myClassObj,并且该实例用作模型对象(无论您的模板在哪里使用(。上面显示了通过继承进行的装饰。另一种方法是改用构图;在这种方法中,您必须在装饰器对象中复制装饰对象所需的所有属性(和其他功能(。

请注意,通过修饰,您还可以选择实现 INotifyPropertyChanged ,以便在实际上影响 getOtherObj() 方法返回值的基础数据发生变化时允许更新绑定状态。它甚至允许属性设置者访问该基础数据,如果需要通过模型对象对其进行修改。


其他选项包括:

  1. 编写自己的 XAML 标记扩展,以处理要使用的扩展方法语法。这将在 XAML 中提供类似的语法(但使用你自己的扩展而不是{Binding}扩展(。在这种方法中,您可能仍希望创建一个通用代理对象,该对象可以类似于上面建议的装饰器对象进行配置,以便它可以参与绑定到实际目标属性(即 Text (。
  2. 写入附加属性。在这种情况下,XAML 看起来与你拥有的不符;而不是绑定到 Text 属性,您将拥有一些附加属性,例如 MyAttachedPropertyClass.MyAttachedProperty="MyStaticClass.getOtherObj" ,其中附加属性通过查找(大概是通过反射(并调用 getOtherObj() 扩展方法来设置 Text 属性。您可以根据需要使附加的属性值尽可能复杂,例如使其成为包含目标属性名称以及扩展方法类和名称的可解析字符串值,甚至使其成为存储此类详细信息的用户定义对象。就此而言,您可以拥有一个类似于上一个替代方法中建议的代理对象,而不是只设置一次目标属性。

就个人而言,我更喜欢简单地装饰原始模型对象的想法。这要容易得多,恕我直言,在其实现中更容易理解。我只是提供这些其他的完整性选项,让您了解避免编写显式装饰器所需的内容。:)