【问题标题】:WPF, XML databinding into dependent/cascading ComboBoxesWPF,XML 数据绑定到依赖/级联组合框
【发布时间】:2011-03-24 06:11:19
【问题描述】:

我有一个具有以下结构的 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>

我正在尝试创建一个 WPF 应用程序,其中包含一个包含产品名称的 ComboBox。我对 WPF 完全陌生,所以我不知道我是否以正确的方式做事。选择产品后,应使用该产品的所有组件填充第二个 ComboBox。 And when a Component is chosen, a third ComboBox should be populated with all the SubComponents for that Component.

我不知道如何在 ComboBox 之间建立依赖关系,除了在由独立 ComboBox 触发的事件处理程序中填充依赖 ComboBox。这似乎意味着我需要能够读取 C# 中的 XML,所以我有 ProductsProductComponentSubComponent[Serializable] 类。但是,我试图在我的 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"/>

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

我有几个问题:

  1. 我这样做正确吗?拥有一个独立的 XML 文件,我的 WPF 应用程序从中读取,[Serializable] 类代表 XML 文件中的节点,以便从 C# 中的这些节点中提取数据,使用事件处理程序来编码组合框之间的依赖关系等。李>
  2. 为什么我的产品名称(例如 MyProduct1)没有出现在我的 ComboBox 中?目前它只是显示为空。
  3. 似乎用[Serializable] 类来表示我的XML 节点是多余的/不必要的,因为XAML 已经有XmlDataProvider/XPath 的东西。是这样吗?

编辑:

将我的 ComboBox XAML 更新为以下内容,现在我可以在 ComboBox 中看到我的产品名称列表,感谢decyclone's answer

<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"/>

【问题讨论】:

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


    【解决方案1】:

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

    关于您的第一个(和第三个)问题,我个人更喜欢创建类而不是使用原始 XML。它给了我一些好处,比如

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

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

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

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

    关键是,值得吗?你真的关心这些好处吗?这就像在 DataReader 和 DataSet 之间进行选择一样。对于 readonly 和 displayonly 目的,请使用原始 XML,如果您要经常使用它,请使用类。

    【讨论】:

    【解决方案2】:

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

    <!-- 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"/>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多