c# - 一个 XmlDataProvider WPF 的多个 XPath

标签 c# wpf xpath datagrid xmldataprovider

我有 2 个 DataGrid 和一个用于 XML 文件的 XmlDataProvider。 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>

我需要使用相同的 XmlDataProvider< 显示第一个 DataGrid 中所有元素的属性值,以及第二个 DataGrid 中所有项目的属性值.

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”中设置 Columns XPath 值"和 "/Element/@ID",但仅显示第一个元素。

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

最佳答案

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

<Setting xmlns="">

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

要填充第二个网格的数据,您可以将 ItemsSource 绑定(bind)到第一个 DataGridPath 应为 SelectedItem ,这正是一个XmlElement,它是一个IEnumerable。因此,您可以使用 XPath 将每个 Item 元素的每个属性绑定(bind)到相应的 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的代码可以正常读取(显示)数据,但不支持修改。这是因为我们绑定(bind)数据的方式,实际上底层集合是ChildNodes,它实际上是一个XmlNodeList,这个集合只是实现了IEnumerable接口(interface)。所以不支持编辑。底层集合应实现 IEditableCollectionView 接口(interface)。通过更改绑定(bind)数据的方式,我们可以将底层集合设置为 IEditableCollectionView。事实上,XPath查询数据的方式可以帮助我们获得一个IEditableCollectionView。因此,在本例中,我们尝试使用 XPath 获取底层集合(而不是通过 ChildNodes 访问,后者可通过类型的 SelectedItem 隐式枚举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的示例,实际的表达式取决于隐式的Source

关于c# - 一个 XmlDataProvider WPF 的多个 XPath,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24741958/

相关文章:

c# - 在 .net Core 中使用通用存储库进行单元测试

c# - 使用反射打印自己的方法名、类库(可移植)

c# - WPF 中的透明边框以编程方式

c# - 如何在单独的线程中打开一个窗口?

c# - 一个 C# 项目中的多个 EXE

wpf - WPF 中带有水平子菜单的水平菜单

python - 如何使用 Selenium 单击此按钮?

c# - 使用 Html Agility Pack 从特定位置选择 HTML

ruby - 无法使用 ruby​​ 中的 Mechanize 缩小 xpath 以提取表

c# - 将可为 null 的 DateTime 绑定(bind)到 MaskedTextBox