【问题标题】:How to bind a control to an element of a XmlDocument in the ViewModel (MVVM Pattern)?如何将控件绑定到 ViewModel(MVVM 模式)中的 XmlDocument 元素?
【发布时间】:2011-01-22 07:12:28
【问题描述】:

我正在尝试将 TextBlock 绑定到 XML 文档的元素,如果源是 StaticResouce,它可以正常工作,但我无法弄清楚绑定到同一 XML 文档的语法当通过 ViewModel 暴露时。

这是 XML 文档:

<Books>
    <Book ID="1" Name="ABC" />
    <Book ID="2" Name="DEF" />
    <Book ID="3" Name="XYZ" />
</Books>

绑定到静态资源 = 成功

资源文件包含一个 XmlDataProvider 参考 Books.xml:

<XmlDataProvider x:Key="data" Source="Books.xml"/>

这就是我绑定到 xml 文件的方式。

<TextBlock Text="{Binding Source={StaticResource data},XPath=/Books/Book/@Name}"/>
<XmlDataProvider x:Key="data" Source="../Views/Data.xml" />

正如我之前所说,上面的绑定工作正常,它显示“ABC”。但是,该 XmlDocument 应该来自 SQL Server 并通过 ViewModel(MVVM 模式)公开。

绑定到 ViewModel = FAILED

ViewModel 中的 Books 属性填充了完全相同的 XML(见上文):

public XmlDocument Books { get; set; }

这是我用来绑定到 ViewModel 的语法:

<TextBlock Text="{Binding Books,XPath=/Books/Book/@Name}" />

它没有返回任何东西,我收到以下错误消息:

带有 XPath 的 BindingExpression 无法绑定到非 XML 对象。

非常感谢任何帮助。

【问题讨论】:

    标签: wpf xaml mvvm binding xmldocument


    【解决方案1】:

    在您绑定到静态资源的示例中,您的绑定路径指向一个“适应”您的 XmlDocument 的 XmlDataProvider。而在您的 ViewModel 示例中,您的 Path 是 XmlDocument 本身。要从您的 ViewModel 实现等效绑定,该属性需要公开一个 XmlDataProvider。

    【讨论】:

      【解决方案2】:

      我在另一个讨论板上找到了答案。以下是如何将控件绑定到 ViewModel 中的 XMLDocument 属性。

      <TextBlock DataContext="{Binding Books}" Text="{Binding XPath=/Books/Book/@Name}"/>
      

      现在我可以成功绑定到来自 SQL Server 的 XML 结果。希望能帮助其他有类似问题的人。干杯。

      【讨论】:

        【解决方案3】:

        ColinE 已经完全回答了这个问题。但另一个解决方案是公开属性 BookName。

        public class ViewModel
        {
            public ViewModel(XDocument doc)
            {
                this.Document = doc;
            }
        
            private XDocument Document
            {
                get;
                set;
            }
        
            public string BookName
            {
                get
                {
                    return this.Document
                               .Element("Books")
                               .Element("Book")
                               .Attribute("Name").Value;
                }
            }
        

        那么你应该直接绑定到 Name 属性:

        <TextBlock Text="{Binding BookName}" />
        

        【讨论】:

        • +1 好主意...不是问题的答案,而是更好的方法 IMO
        • 我简化了上面的例子,以便更容易解释问题。实际上,每一行都有几十个字段,要公开每个字段是不可行的。无论如何感谢您的建议。
        【解决方案4】:

        如果您在代码隐藏中绑定到源,则不需要使用 XPath。简单路径就可以了。

        代码隐藏

        this.DataContext = Books;
        

        Xaml

        <TextBlock Text="{Binding Path=Name}"
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-06-20
          • 1970-01-01
          • 2011-02-08
          • 1970-01-01
          • 2014-03-28
          • 2017-02-11
          • 2023-03-31
          相关资源
          最近更新 更多