在 XAML 中引用嵌套属性

Posted

技术标签:

【中文标题】在 XAML 中引用嵌套属性【英文标题】:Referencing nested properties in XAML 【发布时间】:2012-07-19 20:43:36 【问题描述】:

此问题可能与Creating an instance of a nested class in XAML 重复。这个问题和相关的 MSDN 文档都与嵌套类型有关。在这个例子中,类型本身没有嵌套,但语法看起来很熟悉。我不知道这是否证明单独的问题和答案是合理的。

我想使用ObjectDataProvider 访问嵌套属性。我可以访问类型的静态属性,但通过类型的静态属性访问实例属性会导致编译错误。

例如,取以下三个类。

public static class A

   static A()
   
      BProperty = new B();
   

   public static B BProperty  get; private set; 


public class B

   public B()
   
      CProperty = new C();
   

   public C CProperty  get; private set; 

   public string GetValue(string arg)
   
      return arg + " from B";
   


public class C

   public string GetValue(string arg)
   
      return arg + " from C";
   

A 上为BProperty 创建一个ObjectDataProvider 可以使用以下XAML 完成。

<Window.Resources>
   <ObjectDataProvider x:Key="provider"
                       ObjectInstance="x:Static Member=local:A.BProperty"
                       MethodName="GetValue">
      <ObjectDataProvider.MethodParameters>
         <System:String>string argument</System:String>
      </ObjectDataProvider.MethodParameters>
   </ObjectDataProvider>
</Window.Resources>
<Grid>
   <Label Content="Binding Source=StaticResource provider" />
</Grid>

运行此代码会生成一个带有文本的标签:“来自 B 的字符串参数”。

如果我将providerObjectInstance 设置为"x:Static Member=local:A.BProperty.CProperty""x:Static Member=local:A.BProperty+CProperty",我会收到编译错误。

如何从ObjectDataProvider 访问ABProperty 实例上的CProperty

【问题讨论】:

你的类名和属性名是一样的。为了测试,你可以重命名你的类,看看它是否仍然出现? 这个例子是从我的原始代码简化而来的,它的属性名称与它们的返回类型不同。在这种情况下,问题仍然存在。但是,它可能会提高此示例的可读性,因此我将更新代码。 我会说这是因为 B 被实例化为静态的。因此,一旦它被实例化,它的上下文属性就会被忽略。 【参考方案1】:

你能做的最好的就是:

<Window.Resources>
    <ObjectDataProvider x:Key="provider"
                   ObjectType="x:Type local:A"
                   MethodName="GetCValue">
        <ObjectDataProvider.MethodParameters>
            <System:String>string argument</System:String>
        </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>
</Window.Resources>


public class A

    public A()
    
        BProperty = new B();
    

    public B BProperty  get; private set; 

    public string GetCValue(string arg)
    
        return BProperty.CProperty.GetValue(arg);
    


public class B

    public B()
    
        CProperty = new C();
    

    public C CProperty  get; private set; 

    public string GetValue(string arg)
    
        return arg + " from B";
    


public class C

    public string GetValue(string arg)
    
        return arg + " from C";
    

鉴于 ObjectDataProvider

的性质,我会在这种类型的实现中远离静态

如果您想使用分层对象,请考虑实现 MVVM 模式并在 ViewModel 中实现所有对象。

查看本文了解有关 ObjectDataProvider 的更多详细信息: http://msdn.microsoft.com/en-us/magazine/cc163299.aspx

【讨论】:

这也是我得出的解决方案。我希望有办法直接做到这一点。由于 DataObjectProvider 的性质,您提到要远离静态。你能解释一下原因吗? 好吧,公平地说,我有点主观。这是因为我在大多数实现中看到的基于实例的用法。对于您正在做的事情,我个人会使用 MVVM 只是因为它在 ViewModel 的初始设置开销之后为我提供了最大的灵活性。【参考方案2】:

分两步完成:

<Window.Resources>
   <ObjectDataProvider x:Key="providerOfC"
                       ObjectInstance="x:Static Member=local:A.BProperty"
                       MethodName="get_CProperty" />

   <ObjectDataProvider x:Key="provider"
                       ObjectInstance="StaticResource providerOfC"
                       MethodName="GetValue">
      <ObjectDataProvider.MethodParameters>
         <System:String>string argument</System:String>
      </ObjectDataProvider.MethodParameters>
   </ObjectDataProvider>
</Window.Resources>
<Grid>
   <Label Content="Binding Source=StaticResource provider" />
</Grid>

providerOfC 将您带到A.BProperty.CProperty

provider 然后在该实例上调用GetValue("string argument")

【讨论】:

以上是关于在 XAML 中引用嵌套属性的主要内容,如果未能解决你的问题,请参考以下文章

如何在自定义嵌套用户控件中引用另一个 XAML 元素?

简单的嵌套 TreeView Xaml 结构?

在WPF中,如何使用XAML指定嵌套在目录中的文件的路径?

如何在 WPF XAML 中使用嵌套类?

C# 嵌套对象属性

过滤使用嵌套 xaml 数据模板显示的分层对象