如何将父/子ComboBox与XML数据源绑定?

时间:2009-12-15 18:29:22

标签: wpf xml data-binding xaml xpath

我有以下XML(简化示例),它应该在两个ComboBox之间具有父/子关系。父级绑定正确但子级不绑定父级SelectedItem

当我针对xmlns XML设置foobar并删除所有命名空间引用时,它按预期工作。另外,如果我针对ItemsSource="{Binding XPath=fb:foo/fb:bars/fb:bar}"设置comboBar,它会从bar个元素中找到所有foo个节点。

示例(经测试可在XamlPad中使用)

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

  <Page.Resources>
    <XmlDataProvider x:Key="foobarSource" XPath="fb:foobar">
      <XmlDataProvider.XmlNamespaceManager>
        <XmlNamespaceMappingCollection>
          <XmlNamespaceMapping
            Prefix="fb" Uri="http://foo.bar/1.0/foobar.xsd"/>
        </XmlNamespaceMappingCollection>
      </XmlDataProvider.XmlNamespaceManager>
      <x:XData>
        <foobar xmlns="http://foo.bar/1.0/foobar.xsd">
          <foo name="Foo 1">
            <bars name='bars 1'>
              <bar name="first"/>
              <bar name="second"/>
            </bars>
          </foo>
          <foo name="Foo 2">
            <bars name='bars 2'>
              <bar name="third"/>
              <bar name="fourth"/>
            </bars>
          </foo>
        </foobar>
      </x:XData>
    </XmlDataProvider>
    <DataTemplate x:Key="comboTemplate">
      <TextBlock Text="{Binding XPath=@name}" />
    </DataTemplate>
  </Page.Resources>

  <StackPanel DataContext="{StaticResource foobarSource}">
    <ComboBox Width="150" x:Name="comboFoo"
              IsSynchronizedWithCurrentItem="True"
              ItemsSource="{Binding XPath=fb:foo}"
              ItemTemplate="{StaticResource comboTemplate}"/>
    <ComboBox Width="150" x:Name="comboBar"
              IsSynchronizedWithCurrentItem="True"
              DataContext="{Binding SelectedItem, ElementName=comboFoo}"
              ItemsSource="{Binding XPath=fb:bars/fb:bar}"
              ItemTemplate="{StaticResource comboTemplate}"/>
  </StackPanel>
</Page>

1 个答案:

答案 0 :(得分:1)

如果你使用Visual Studio而不是XamlPad,你会看到你得到一个XPathException,说明需要Namespace Manager或XsltContext。

<Window.Resources>

    <XmlNamespaceMappingCollection x:Key="fbNamespaces">
        <XmlNamespaceMapping Prefix="fb" Uri="http://foo.bar/1.0/foobar.xsd" />
    </XmlNamespaceMappingCollection>

    <XmlDataProvider x:Key="foobarSource" XPath="fb:foobar">
        <XmlDataProvider.XmlNamespaceManager>
            <XmlNamespaceMappingCollection>
                <XmlNamespaceMapping Prefix="fb" Uri="http://foo.bar/1.0/foobar.xsd" />
            </XmlNamespaceMappingCollection>
        </XmlDataProvider.XmlNamespaceManager>
        <x:XData>
            <foobar xmlns="http://foo.bar/1.0/foobar.xsd">
                <foo name="Foo 1">
                    <bars name='bars 1'>
                        <bar name="first" />
                        <bar name="second" />
                    </bars>
                </foo>
                <foo name="Foo 2">
                    <bars name='bars 2'>
                        <bar name="third" />
                        <bar name="fourth" />
                    </bars>
                </foo>
            </foobar>
        </x:XData>
    </XmlDataProvider>

    <DataTemplate x:Key="comboTemplate">
        <TextBlock Text="{Binding XPath=@name}" />
    </DataTemplate>

</Window.Resources>

<StackPanel 
    Binding.XmlNamespaceManager="{StaticResource fbNamespaces}">

    <ComboBox Width="150" x:Name="comboFoo" 
          IsSynchronizedWithCurrentItem="True" 
          DataContext="{StaticResource foobarSource}"    
          ItemsSource="{Binding XPath=fb:foo}" 
          ItemTemplate="{StaticResource comboTemplate}" />
    <ComboBox Width="150" 
          IsSynchronizedWithCurrentItem="True" 
          DataContext="{Binding SelectedItem, ElementName=comboFoo}" 
          ItemsSource="{Binding XPath=fb:bars/fb:bar}" 
          ItemTemplate="{StaticResource comboTemplate}" />

</StackPanel>