WPF,XML数据绑定到依赖/级联组合框

时间:2010-08-02 14:35:21

标签: c# wpf data-binding xaml xml-serialization

我有一个XML文件,结构如下:

<Products>
  <Product name="MyProduct1">
    <Components>
      <Component name="MyComponent1">
        <SubComponents>
          <SubComponent name="MySubComponent1"/>
          <SubComponent name="MySubComponent2"/>
          ...more SubComponent nodes...
        </SubComponents>
      </Component>
      ...more Component nodes...
    </Components>
  </Product>
  ...more Product nodes...
</Products>

我正在尝试创建一个包含ComboBox且其中包含产品名称的WPF应用。我是WPF的新手,所以我不知道我是否正确地做事。选择产品时,应使用该产品的所有组件填充第二个ComboBox。当选择Component时,应该使用该Component的所有SubComponents填充第三个ComboBox。

我不知道如何在ComboBox之间建立依赖关系,除了在独立的ComboBox触发的事件处理程序中填充依赖的ComboBox。这似乎意味着我需要能够在C#中读取XML,因此我有ProductsProductComponentSubComponent的{​​{3}}个类。但是,我试图在我的XAML中进行XML数据绑定:

<Window.Resources>
    <XmlDataProvider Source="Products.xml"
                     XPath="Products/Product"
                     x:Key="productsXml"/>
</Window.Resources>

我目前没有在我的第一个ComboBox中看到产品名称列表,其XAML如下:

<ComboBox Height="23" HorizontalAlignment="Left" Margin="138,116,0,0"
          Name="cbo_product" VerticalAlignment="Top" Width="120"
          ItemsSource="{Binding Source=productsXml, XPath=@name}"
          SelectionChanged="product_SelectionChanged"/>

Products XML应该是只读的 - 用户将无法从应用程序更改XML中的任何值。我只想阅读XML数据并将其显示在应用程序中。

我有几个问题:

  1. 我正确地谈到这个吗?有一个独立的XML文件,我的WPF应用程序从中读取,有[Serializable]个类表示XML文件中的节点,目的是从C#中的那些节点中提取数据,使用事件处理程序来编写ComboBox之间的依赖关系等。
  2. 为什么我的产品名称(例如MyProduct1)不会显示在我的ComboBox中?目前它只显示为空。
  3. 由于XAML已经具有[Serializable] / XPath内容,因此用于表示我的XML节点的XmlDataProvider类似乎是多余/不必要的。是这种情况吗?
  4. 修改

    将我的ComboBox XAML更新为以下内容,现在我在ComboBox中看到了我的产品名称列表,感谢[Serializable]

    <ComboBox Height="23" HorizontalAlignment="Left" Margin="138,116,0,0"
              Name="cbo_product" VerticalAlignment="Top" Width="120"
              ItemsSource="{Binding Source={StaticResource productsXml}}"
              DisplayMemberPath="@name"
              SelectionChanged="product_SelectionChanged"/>
    

2 个答案:

答案 0 :(得分:2)

ItemsSource属性应设置为要在列表中显示的项目集合,在您的案例中为XmlDataProvider。用户StaticResource定位它,因为它被定义为资源。 DisplayMemberPath属性应该用于选择应该使用哪个属性来显示组合框中的文本。

关于你的第一个(&amp; 3ed)问题,我个人喜欢创建类而不是使用原始XML。它给了我很少的好处,比如

  • 添加包装器属性。例如,FullName = FirstName +“”+ LastName属性。

  • 每次我想访问值(总是字符串)时,我都不必检查空值和类型安全性。

  • 我可以将自己的行为添加为对执行小任务非常有用的方法。

  • 控制序列化方法并使用属性在其中注入自定义逻辑。

重点是,值得吗?你真的关心这些好处吗?这就像在DataReader和DataSet之间进行选择一样。对于readonly和displaylyly目的,使用原始XML,如果你打算玩它很多,使用类。

答案 1 :(得分:2)

好的,既然我找到了more specific question的答案,我想我也知道这个问题的答案。对于XML中的不同节点,我不需要[Serializable]个类,因为我可以使用XAML和XPath来创建级联/依赖的ComboBoxes:

<!-- Independent -->
<ComboBox Height="23" HorizontalAlignment="Left" Margin="138,116,0,0"
          Name="cbo_product" VerticalAlignment="Top" Width="120"
          ItemsSource="{Binding Source={StaticResource productsXml}}"
          DisplayMemberPath="@name"/>

<!-- Dependent -->
<ComboBox Height="23" HorizontalAlignment="Left" Margin="138,151,0,0"
          Name="cbo_component" VerticalAlignment="Top" Width="201"
          DataContext="{Binding ElementName=cbo_product, Path=SelectedItem}"
          ItemsSource="{Binding XPath=Components/Component}"
          DisplayMemberPath="@name"/>