使用命名空间进行XML数据绑定

时间:2008-10-10 04:15:51

标签: c# wpf xml data-binding namespaces

我想使用XML文档的数据绑定来填充一个显示人员列表详细信息的简单表单。我现在已经完成了所有设置和工作:

<Window x:Class="DataBindingSample.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1">
<Window.Resources>
    <XmlDataProvider x:Key="xmlProvider" XPath="People" Source="c:\someuri.xml"/>
</Window.Resources>
<Grid>        
    <ListBox Name="personList" ItemsSource="{Binding Source={StaticResource xmlProvider}, XPath=Person}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding XPath=Name}" />
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

    <GroupBox Header="GroupBox" Name="groupBox1" DataContext="{Binding ElementName=personList, Path=SelectedItem}">
        <Grid>
            <TextBox Name="nameText" Text="{Binding XPath=Name}"/>
            <ComboBox Name="genderCombo" Text="{Binding XPath=Gender}">
                <ComboBoxItem>Male</ComboBoxItem>
                <ComboBoxItem>Female</ComboBoxItem>
            </ComboBox>
        </Grid>
    </GroupBox>
</Grid>
</Window>

(为清晰起见,已移除所有位置/布局元素)

现在这很棒!如果我为它提供了一些与提供的路径匹配的XML,我会在列表框中获得一个名称列表,在单击时在相应的字段中显示名称和性别。当我开始尝试在XML源中使用名称空间时,问题出现了。然后XAML变为如下所示:

<Window x:Class="DataBindingSample.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1">
<Window.Resources>
    <XmlNamespaceMappingCollection x:Key="namespaceMappings">
        <XmlNamespaceMapping Uri="http://www.mynamespace.com" Prefix="mns"/>
    </XmlNamespaceMappingCollection>
    <XmlDataProvider x:Key="xmlProvider" XmlNamespaceManager="{StaticResource namespaceMappings}" XPath="mns:People" Source="c:\someuriwithnamespaces.xml"/>
</Window.Resources>
<Grid>        
    <ListBox Name="personList" ItemsSource="{Binding Source={StaticResource xmlProvider}, XPath=mns:Person}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding XPath=mns:Name}" />
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

    <GroupBox Header="GroupBox" Name="groupBox1" DataContext="{Binding ElementName=personList, Path=SelectedItem}">
        <Grid>
            <TextBox Name="nameText" Text="{Binding XPath=mns:Name}"/>
            <ComboBox Name="genderCombo" Text="{Binding XPath=mns:Gender}">
                <ComboBoxItem>Male</ComboBoxItem>
                <ComboBoxItem>Female</ComboBoxItem>
            </ComboBox>
        </Grid>
    </GroupBox>
</Grid>
</Window>

使用此代码(当然还有适当的命名空间的xml),列表框仍会正确显示名称,但单击这些名称不再更新名称和性别字段!我怀疑是,xml命名空间在某种程度上对groupbox的DataContext产生了不利影响,但我不确定为什么或如何。有谁知道如何在此上下文中使用XML命名空间?

2 个答案:

答案 0 :(得分:2)

我还在MSDN WPF表单上asked this question。 Marco Zhou用这个回答了我,这最终是我寻求的答案。我在这里转载它是为了寻找相同答案的人的利益:

  

这有效:

     

                                           

    <XmlDataProvider x:Key="dataProvider"
                     XmlNamespaceManager="{StaticResource namespaceMappings}"
                     XPath="p:players/p:player">
        <x:XData>
            <p:players xmlns:p="http://www.footballism.com/2005/SoccerPlayers">
                <p:player>
                    <p:fullName>Sebastian Batistuta</p:fullName>
                    <p:age>26</p:age>
                </p:player>
                <p:player>
                    <p:fullName>Andriey Shevchenko</p:fullName>
                    <p:age>30</p:age>
                </p:player>
                <p:player>
                    <p:fullName>Paviel Nedved</p:fullName>
                    <p:age>21</p:age>
                </p:player>
                <p:player>
                    <p:fullName>David Beckham</p:fullName>
                    <p:age>19</p:age>
                </p:player>
            </p:players>
        </x:XData>
    </XmlDataProvider>
</Page.Resources>
<StackPanel>
    <TextBlock
        Text="{Binding XPath=p:fullName}"
        FontWeight="Bold"
        Binding.XmlNamespaceManager="{StaticResource namespaceMappings}"
        DataContext="{Binding ElementName=listBox, Path=SelectedItem}"/>
    <ListBox ItemsSource="{Binding Source={StaticResource dataProvider}}"
             x:Name="listBox"
             DisplayMemberPath="p:fullName">
    </ListBox>
</StackPanel> </Page>
     

我想看看代码之后,   你应该能够理解为什么   指定后它可以工作   Binding.XmlNamespaceManager附加   TextBlock的属性。

     

ListBox是绑定到数据的数据   具有xml命名空间的提供者   映射信息,但绑定   在TextBlock上没有这个   信息,这就是它失败的原因。

     

实际上,在做主人细节时   数据绑定,它更合适   做类似以下的事情:

     

                                           

    <XmlDataProvider x:Key="dataProvider"
                     XmlNamespaceManager="{StaticResource namespaceMappings}"
                     XPath="p:players/p:player">
        <x:XData>
            <p:players xmlns:p="http://www.footballism.com/2005/SoccerPlayers">
                <p:player>
                    <p:fullName>Sebastian Batistuta</p:fullName>
                    <p:age>26</p:age>
                </p:player>
                <p:player>
                    <p:fullName>Andriey Shevchenko</p:fullName>
                    <p:age>30</p:age>
                </p:player>
                <p:player>
                    <p:fullName>Paviel Nedved</p:fullName>
                    <p:age>21</p:age>
                </p:player>
                <p:player>
                    <p:fullName>David Beckham</p:fullName>
                    <p:age>19</p:age>
                </p:player>
            </p:players>
        </x:XData>
    </XmlDataProvider>
</Page.Resources>
<StackPanel DataContext="{Binding Source={StaticResource dataProvider}}">
    <TextBlock
        Text="{Binding XPath=p:fullName}"
        FontWeight="Bold"/>
    <ListBox ItemsSource="{Binding}"
             x:Name="listBox"
             DisplayMemberPath="p:fullName"
             IsSynchronizedWithCurrentItem="True">
    </ListBox>
</StackPanel> </Page>
     

希望这会让事情变得清晰起来   位。

答案 1 :(得分:1)

您可以在XPath查询中使用本地名称,如下所示:

 <TextBox Name="nameText">
    <TextBox.Text>
       <Binding XPath="*[local-name()='Name']" />
    </TextBox.Text>
 </TextBox>