views:

32

answers:

2

I have XML in the following format:

<Products>
  <Product name="MyProduct1">
    <Components>
      <Component name="MyComponent1">
        <Teams>
          <Team id="1"/>
          <Team id="4"/>
        </Teams>
      </Component>
    </Components>
  </Product>
</Products>

This is stored in an external XML file that is included via an XmlDataProvider in my XAML:

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

You'll see that the Team nodes have only an id attribute; this links them to other XML that is embedded directly in my XAML:

<XmlDataProvider x:Key="teamsXml" XPath="Teams/Team">
    <x:XData>
        <Teams xmlns="">
            <Team name="Team A" id="1"/>
            <Team name="Team B" id="2"/>
            <Team name="Team C" id="3"/>
            <Team name="Team D" id="4"/>
        </Teams>
    </x:XData>
</XmlDataProvider>

I have the following ComboBox in my XAML:

<ComboBox Height="23" HorizontalAlignment="Left" Margin="133,217,0,0"
          Name="cbo_team" VerticalAlignment="Top" Width="148"
          DataContext="{Binding ElementName=cbo_component, Path=SelectedItem}"
          ItemsSource="{Binding XPath=Teams/Team}"
          SelectedIndex="0" />

This ComboBox shows a list of Teams associated with the currently selected Component. I need to keep DataContext and ItemsSource the same here so that only the related Teams are shown, and not all available Teams. However, I don't want to show the Team id attribute in the ComboBox, I want to show the name attribute as it is defined in teamsXml, e.g., Team A. How can I use a DataTemplate and somehow get the Team name from teamsXml when I have the Team id from productsXml? I also want the value of the ComboBox to be the name attribute.

Edit:

I'm wondering if something like this is a step in the right direction:

<ComboBox Height="23" HorizontalAlignment="Left" Margin="133,217,0,0"
            Name="cbo_team" VerticalAlignment="Top" Width="148"
            DataContext="{Binding ElementName=cbo_component, Path=SelectedItem}"
            ItemsSource="{Binding XPath=Teams/Team}"
            SelectedIndex="0">
    <ComboBox.DisplayMemberPath>
        <Binding Source="{StaticResource teamsXml}"
                 XPath="???"/> <!-- Need to select the @name attribute of the node
                                    whose @id attribute is the same value as the
                                    current selected item in this ComboBox -->
    </ComboBox.DisplayMemberPath>
</ComboBox>
A: 

I'd use Linq to xml and fill a CollectionViewSource. Then bind to that rather than xmlDataProvider.

Chris
Okay. It seems like I could write a C# method that, given `id`s, would return `name`s, using LINQ to XML. How would I call this method and give it `id`s from XAML, though?
Sarah Vessels
Looks like this might be useful: http://stackoverflow.com/questions/663356/how-can-i-call-a-bound-method-in-xaml-with-the-parameter-of-a-tabitems-name
Sarah Vessels
A: 

Once again, this guy's article helped me out. I moved my Teams XML into my Products.xml file, so I have the following format:

<Products>
  <Product name="MyProduct1">
    <Components>
      <Component name="MyComponent1">
        <Teams>
          <Team id="1"/>
          <Team id="4"/>
        </Teams>
      </Component>
    </Components>
  </Product>
  <Teams>
    <Team name="Team A" id="1"/>
    <Team name="Team B" id="2"/>
    <Team name="Team C" id="3"/>
    <Team name="Team D" id="4"/>
  </Teams>  
</Products>

Then, I did the following for my ComboBox in XAML:

<ComboBox Height="23" HorizontalAlignment="Left" Margin="133,218,0,0"
          Name="cbo_team" VerticalAlignment="Top" Width="148"
          DataContext="{Binding ElementName=cbo_component, Path=SelectedItem}">
    <ComboBox.ItemsSource>
        <Binding XPath="Teams/Team/@id"
                 Converter="{StaticResource xmlConverter}">
            <Binding.ConverterParameter>
                <local:XmlConverterParameter
                    XPathTemplate="/Products/Teams/Team[{0}]"
                    XPathCondition="@id='{0}'" />
            </Binding.ConverterParameter>
        </Binding>
    </ComboBox.ItemsSource>
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding XPath=@name}" />
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

I had to include the following in my <Window.Resources> in XAML:

<local:XmlConverter x:Key="xmlConverter"/>

And, following his tutorial, I created two C# classes: XmlConverter and XmlConverterParameter. Now my ComboBox converts a team id to a name and displays the name, so my XML is fairly DRY because the team names are only defined in one place.

Sarah Vessels