2

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

我需要在 first 中显示所有 Elements 的属性DataGrid值,并在 secondDataGrid中使用 same显示所有 Items 的属性值XmlDataProvider

XAML 在 first 中显示所有元素的属性值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>
...

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

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

4

1 回答 1

3

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

<Setting xmlns="">

否则它将使用xmlns窗口范围内的分配(当然是"http://schemas.microsoft.com/winfx/2006/xaml/presentation")并且元素的路径将不正确。

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

<!-- 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来获取底层集合(而不是通过typeChildNodes隐式可枚举的 via访问):SelectedItemXmlElement

<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,实际的表达式取决于隐含的Source

于 2014-07-14T18:03:36.017 回答