一个XmlDataProvider WPF的几个XPath

时间:2014-07-14 17:08:58

标签: c# wpf xpath datagrid xmldataprovider

我有2个DataGrid和一个XmlDataProvider用于XML文件。 XML文件结构如下所示:

<Setting>
  <Element Name="..." Offset="..." ID="...">
    <Item Name="..." Type="..." Count="..." ID="..." />
    <Item Name="..." Type="..." Count="..." ID="..." />
    <Item Name="..." Type="..." Count="..." ID="..." />
    ...
  </Element>
  <Element Name="..." Offset="..." ID="...">
    <Item Name="..." Type="..." Count="..." ID="..." />
    <Item Name="..." Type="..." Count="..." ID="..." />
  </Element>
  ...
</Setting>

我需要在第一个DataGrid中显示所有元素的属性值,并使用相同的DataGrid显示第二个XmlDataProvider中所有项目的属性值。

XAML在第一个DataGrid中显示所有元素的属性值:

...
<Grid.DataContext>
  <XmlDataProvider x:Name="xml_setting" XPath="/Setting/Element"/>
</Grid.DataContext>
<DataGrid ItemsSource="{Binding}">
  <DataGrid.Columns>
    <DataGridTextColumn Header="Name" Width="*" Binding="{Binding XPath=@Name}"/>
    <DataGridTextColumn Header="Offset" Width="80" Binding="{Binding XPath=@Offset}"/>
    <DataGridTextColumn Header="ID" Width="80" Binding="{Binding XPath=@ID}"/>
  </DataGrid.Columns>
</DataGrid>
...

我尝试在“/ Setting”中设置XmlDataProvider XPath值,在“/ Element / @ Name”,“/ Element / @ Offset”和“/ Element / @ ID”中设置Columns XPath值“,但只显示第一个元素。

如何使用一个XmlDataProvider绑定到不同DataGrids的不同列,以显示XML文件的不同节点的属性值?

1 个答案:

答案 0 :(得分:3)

问题是你必须将XML根节点的默认命名空间设置为空字符串:

<Setting xmlns="">

否则它将使用窗口范围中指定的xmlns(当然是"http://schemas.microsoft.com/winfx/2006/xaml/presentation")和元素&#39;路径不正确。

要填充第二个网格的数据,您可以将ItemsSource绑定到第一个DataGridPath应该是SelectedItem,这正是{{1}这是一个XmlElement。因此,您可以使用IEnumerable将每个XPath元素的每个属性绑定到相应的Item,如下所示:

DataGridTextColumn

更新:第二个<!-- the first Grid --> <DataGrid ItemsSource="{Binding}" AutoGenerateColumns="False" Name="grid1"> <DataGrid.Columns> <DataGridTextColumn Header="Name" Width="*" Binding="{Binding XPath=@Name}"/> <DataGridTextColumn Header="Offset" Width="80" Binding="{Binding XPath=@Offset}"/> <DataGridTextColumn Header="ID" Width="80" Binding="{Binding XPath=@ID}"/> </DataGrid.Columns> </DataGrid> <!-- the second Grid --> <DataGrid Grid.Column="1" ItemsSource="{Binding ElementName=grid1,Path=SelectedItem}" AutoGenerateColumns="False"> <DataGrid.Columns> <DataGridTextColumn Header="Name" Width="*" Binding="{Binding XPath=@Name}"/> <DataGridTextColumn Header="Type" Width="100" Binding="{Binding XPath=@Type}"/> <DataGridTextColumn Header="Count" Width="80" Binding="{Binding XPath=@Count}"/> <DataGridTextColumn Header="ID" Width="80" Binding="{Binding XPath=@ID}"/> </DataGrid.Columns> </DataGrid> 的上述代码可以正常读取(显示)数据,但不支持修改。这是因为我们绑定数据的方式,实际上底层集合是DataGrid,实际上是ChildNodes,这个集合只是实现了XmlNodeList接口。所以它不支持编辑。底层集合应该实现IEnumerable接口。通过更改绑定数据的方式,我们可以将基础集合设置为IEditableCollectionView。事实上,IEditableCollectionView查询数据的方式可以帮助我们获得XPath。因此,在这种情况下,我们尝试使用IEditableCollectionView来获取基础集合(而不是通过XPath进行访问,ChildNodes可以通过类型SelectedItem的{​​{1}}隐式枚举:

XmlElement

现在它就像一个魅力(经过测试)。

更新:要按名称过滤元素,您必须使用属性元素语法(非属性语法),如下所示:

<DataGrid Grid.Column="1" 
          DataContext="{Binding ElementName=grid1,Path=SelectedItem}"
          ItemsSource="{Binding XPath=Item}"
          AutoGenerateColumns="False">
    <!-- .... -->
</DataGrid>

请注意,上面的代码只是如何指定<DataGrid Grid.Column="1" AutoGenerateColumns="False"> <DataGrid.ItemsSource> <Binding XPath="Setting/Element[@Name='SomeName']"/> </DataGrid.ItemsSource> <!-- ...... --> </DataGrid> 的示例,实际表达式取决于隐式XPath