views:

98

answers:

2

I have an XML file with the following structure:

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

I'm trying to create a WPF app that has a ComboBox with the Product names in it. I am completely new to WPF so I don't know if I'm going about things the right way. When a Product is chosen, a second ComboBox should be populated with all the Components for that Product. And when a Component is chosen, a third ComboBox should be populated with all the SubComponents for that Component.

I don't know how to set up a dependency between ComboBoxes except to populate the dependent ComboBox inside an event handler triggered by the independent ComboBox. This seems to imply I need to be able to read the XML in C#, so I have [Serializable] classes for Products, Product, Component, and SubComponent. However, I was trying to do XML databinding in my XAML:

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

I'm currently not seeing a list of Product names in my first ComboBox, whose XAML is the following:

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

The Products XML should be read-only--the user won't be able to change any values in the XML from the app. I just want to read the XML data and display it in the app.

I have a few questions:

  1. Am I going about this correctly? Having a standalone XML file from which my WPF app reads, having [Serializable] classes representing the nodes in the XML file for the purpose of extracting data from those nodes in C#, using an event handler to code dependencies between ComboBoxes, etc.
  2. Why don't my product names, e.g., MyProduct1, show up in my ComboBox? Currently it just shows up empty.
  3. It seems almost like having [Serializable] classes for representing my XML nodes is redundant/unnecessary since XAML already has the XmlDataProvider/XPath stuff. Is this the case?

Edit:

Updated my ComboBox XAML to the following and now I see my list of Product names in the ComboBox, thanks to 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"/>
+1  A: 

Hi,

The ItemsSource property should be set to a collection of items that are to be displayed in the list which is XmlDataProvider in your case. User StaticResource to locate it since it is defined as a resource. The DisplayMemberPath property should be used to select what property should be used to display text in combobox.

Regarding your 1st (& 3ed) question, I personally like create classes than using raw XML. It gives me few benefits like

  • Adding wrapper properties. For example, FullName = FirstName + " " + LastName property.

  • I dont have to check for empty values and type safety everytime I want to access the values (which are always strings).

  • I can add my own behaviors as methods which can be really useful for doing little tasks.

  • Control the serialization method and inject custom logic in it using attributes.

The point is, is it worth it? Do you really care for these benefits? It's just like choosing between DataReader and DataSet. For readonly and displayonly purpose, use raw XML and if you are going to play with it a lot, use classes.

decyclone
Here is a good example on how to do that.http://msdn.microsoft.com/en-us/library/system.windows.data.xmldataprovider.aspx
decyclone
This answered question 2) for me. :) Thanks!
Sarah Vessels
A: 

Okay, since I found an answer to my more specific question, I think I know the answer to this question, too. I don't need [Serializable] classes for the different nodes in my XML, because I can just use XAML and XPath to create cascading/dependent 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"/>
Sarah Vessels