如何将 xml 正确绑定到 WPF DataGrid?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2199721/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 21:28:35  来源:igfitidea点击:

How to bind xml to the WPF DataGrid correctly?

wpfdata-bindingwpfdatagrid

提问by IanGilham

I have looked for and tried various solutions but so far none of them solve my problem. I am using the built-in DataGrid from WPF in Visual Studio 2010/.NET4 to display data from an XML document stored as an XDocument.

我已经寻找并尝试了各种解决方案,但到目前为止,没有一个能解决我的问题。我在 Visual Studio 2010/.NET4 中使用来自 WPF 的内置 DataGrid 来显示存储为 XDocument 的 XML 文档中的数据。

My code all runs fine, and I have verified that the XDocument is present and correct. The DataGrid does not display any data, however.

我的代码运行良好,并且我已验证 XDocument 存在且正确。但是,DataGrid 不显示任何数据。

The XML looks like this (simplified for clarity):

XML 如下所示(为清晰起见进行了简化):

<data>
  <track>
    <id>211</id>
    <name>Track Name</name>
    <duration>156</duration>
    <artist_id>13</artist_id>
    <artist_name>Artist Name</artist_name>
    <album_id>29</album_id>
    <album_name>Album Name</album_name>
  </track>
...
</data>

My XAML looks like this:

我的 XAML 看起来像这样:

<DataGrid x:Name="LibraryView" Grid.Row="1"
              DataContext="{Binding Path=TrackList}" ItemsSource="{Binding XPath=/data/track}">
    <DataGridTextColumn Header="Title" Binding="{Binding XPath=name}"/>
    <DataGridTextColumn Header="Artist" Binding="{Binding XPath=artist_name}"/>
    <DataGridTextColumn Header="Album" Binding="{Binding XPath=album_name}"/>
    <DataGridTextColumn Header="Length" Binding="{Binding XPath=duration}"/>
</DataGrid>

The C# that backs it up just assigns a new XDocument (downloaded from a web service) to the TrackList property (which implements INotifyPropertyChanged). No further processing is done on it.

支持它的 C# 只是将一个新的 XDocument(从 Web 服务下载)分配给 TrackList 属性(它实现了 INotifyPropertyChanged)。不对它做进一步的处理。

I have previously tried using XLinq, to bind to a query result, which didn't work either (same problem), so I thought I'd try the XPath approach to avoid writing a potentially buggy Linq statement, and try to find the problem.

我之前曾尝试使用 XLinq 绑定到查询结果,但也没有奏效(同样的问题),所以我想我会尝试使用 XPath 方法来避免编写可能有问题的 Linq 语句,并尝试找出问题所在.

I am running out of ideas for how to get the DataGrid to display correctly. My understanding of how this is supposed to work is clearly lacking, so I would greatly appreciate any help offered.

我对如何让 DataGrid 正确显示的想法不多了。我显然缺乏对这应该如何工作的理解,因此我将不胜感激提供的任何帮助。

Edit: It is worth noting that I have some flexibility with the input data format, as I am downloading raw XML myself. I will try some of the suggestions and see what I can get to work.

编辑:值得注意的是,我对输入数据格式有一定的灵活性,因为我自己正在下载原始 XML。我会尝试一些建议,看看我能做些什么。

回答by Natxo

I used XLinq and worked fine, using a XElement instead of a XDocument :

我使用 XLinq 并且工作正常,使用 XElement 而不是 XDocument :

XElement TrackList = XElement.Load("List.xml");
LibraryView.DataContext = TrackList;

Xaml:

Xml:

<DataGrid x:Name="LibraryView" ItemsSource="{Binding Path=Elements[track]}">
    <DataGrid.Columns>
         <DataGridTextColumn Header="Artist" Binding="{Binding Path=Element[artist_name].Value}"/>
         <DataGridTextColumn Header="Album" Binding="{Binding Path=Element[album_name].Value}"/>
         <DataGridTextColumn Header="Length" Binding="{Binding Path=Element[duration].Value}"/>
    </DataGrid.Columns>
</DataGrid>

回答by Hyman Ukleja

Binding XPath is only relevant if you are binding to something that is an XmlNode (e.g. you are using XmlDataProvider). See here.

仅当您绑定到 XmlNode(例如,您使用 XmlDataProvider)时,绑定 XPath 才相关。见这里

XPath does not work with XDocument classes. The only way to bind to properties of an XDocument is the normal Path syntax, which is not XML aware.

XPath 不适用于 XDocument 类。绑定到 XDocument 属性的唯一方法是正常的 Path 语法,它不支持 XML。

Your best bet is either to use the XmlDataSource, or convert your Xml document via XDocument into a POCO. That is pretty simple using LINQ:

您最好的选择是使用 XmlDataSource,或者通过 XDocument 将您的 Xml 文档转换为 POCO。使用 LINQ 非常简单:

XDocument doc = XDocument.Load(xmlFile);

            var tracks = from track in doc.Descendants("data") 
                    select new Track()
                               {
                                   Name= track.Element("name").Value,    
                                   Duration= track.Element("duration").Value,    
                                   etc ... 
                               };
LibraryView.ItemsSource = tracks;