2014-01-29 130 views
0

我想从XML获取我的所有信息到Datagrid。XML Datagrid根元素 - foreach循环

目前我有这样的:

class ColumnNames 
{ 
    public string id { get; set; } 
    public string Name { get; set; } 
    public string Surname { get; set; } 
    public string Computer { get; set; } 

    public ColumnNames(
     string id, 
     string Name, 
     string Surname, 
     string Computer, 
    { 
     this.id = id; 
     this.Name = Name; 
     this.Surname = Surname; 
     this.Computer = Computer; 
    } 
} 

private void DataGrid_Loaded(object sender, RoutedEventArgs e) 
{ 

    XDocument getElement = XDocument.Load("details.xml"); 

    foreach (var npc in getElement.Descendants("user")) 
    { 
     string id = npc.Attribute("id").Value; 
     string Name = npc.Attribute("Name").Value; 
     string Surname = npc.Attribute("Surname").Value; 
     string Computer = npc.Attribute("Computer").Value; 

     var items = new List<ColumnNames>(); 
     items.Add(new ColumnNames(id, Name, Surname, Computer)); 
     var grid = sender as DataGrid; 
     grid.ItemsSource = items; 
    } 
} 

这是我的XML

<info> 
     <user id="1" Name="Max0" Surname="0test" Computer="0" /> 
     <user id="2" Name="Max1" Surname="1test" Computer="1" /> 
     <user id="3" Name="Max2" Surname="2test" Computer="2" /> 
     <user id="4" Name="Max3" Surname="3test" Computer="3" /> 
     <user id="5" Name="Max4" Surname="4test" Computer="4" /> 
     <user id="6" Name="Max5" Surname="5test" Computer="5" /> 
    </info> 

我所试图做的就是把所有的根元素中的数据与列ID的数据网格,姓名和电脑。我的问题是,在目前它只是变得第一项,并当我试图使用以下命令:

foreach (var npc in getElement.Root("info")) 

我得到了一个错误说

“非可调用成员“的System.Xml。 Linq.XDocument.Root'不能像 一样使用。“

我不知道我该怎么做这项工作,已经有相当一段时间了,我一直试图让这个固定的,一些帮助很好。谢谢。


UPDATE:

这是新代码后,大卫慷慨地帮助了我。虽然它还没有工作。

+0

你确定DataBind()正在被调用..你有没有通过调试器,并且正在执行这段代码。代码对我来说看起来很好。 –

+0

它只会经历一次,但其余的不会经过它。 –

+0

经历了一次,fo​​reach循环? 1.确保你的XML文件是正确的。 2.确保正确重建解决方案并运行新代码。 –

回答

1

你靠近...

foreach (var npc in getElement.Descendants("user")) 

实际上做的工作,是正确的,与给定的XML结构。尽管如此,请参阅我的答案的底部以了解一个重要的区别。

的问题是,您要设置grid.ItemsSource = items;foreach循环中,从而只增加每个foreach循环时左右一个项目,而你总是只需在您的DataGrid中的最后一个项目结束。

此外,您还需要持有foreach循环以外的项目列表,否则它只存在于foreach内部(仅有scope)。

为了解决这个问题,你需要移动grid.ItemsSource = items;foreach循环之后,和foreach循环前移到列表创建于:

// Your code 
private void DataGrid_Loaded(object sender, RoutedEventArgs e) 
{  
    // getElement is a weird name for this object :) 
    XDocument getElement = XDocument.Load("details.xml"); 

    // Create your List of ColumnNames outside the foreach to use later 
    var items = new List<ColumnNames>(); 

    foreach (var npc in getElement.Descendants("user")) 
    { 
     string id = npc.Attribute("id").Value; 
     string Name = npc.Attribute("Name").Value; 
     string Surname = npc.Attribute("Surname").Value; 
     string Computer = npc.Attribute("Computer").Value; 

     // You are adding an item to the existing List<ColumnNames> now, not a new one each time 
     items.Add(new ColumnNames(id, Name, Surname, Computer)); 
    } 

    // Finally, get a reference to the grid and set the ItemsSource property to use 
    // your full list containing all the items 
    var grid = sender as DataGrid; 
    grid.ItemsSource = items; 

} 

希望这有助于!


关于你尝试在你的foreach循环改变XDocument通话,正如我所说,你实际上有它正常工作...但要解释为什么改变的版本不工作,因为我写的准备,请参阅下面的:

你的主要问题是:XDocumentRoot元素,在这种情况下,<info>

语法你”重新使用,getElement.Root("info")告诉编译器你想调用一个名为Root of XDocument的method--但该方法不存在。这是一个财产。这就是你的错误信息告诉你的。

要解决该问题,

更改foreach使用的XDocument.Elements()方法和一切都会好起来:

foreach (var npc in getElement.Root.Elements("user")) 

或者,因为你已经有了它

foreach (var npc in getElement.Descendants("user")) 

这里的主要区别是.Descendants()将得到任何名为“用户”的节点,不管它有多深泰德; .Elements()只会从当前节点(直接子节点)下一个级别。

所以,尽管您的XML结构看起来工作原理相同,但在您的XML结构发生变化(或场景/项目不同等)时理解这种区别非常重要。


作为便笺,getElement是XDocument对象的奇怪名称;我通常只使用类似... XDOC


一个更多更新 - 为什么不是这方面的工作?

当我意识到这是一个WPF数据网格,并且您正在加载一个本地XML文件时,它在我身上发现您的网格不显示任何内容,因为XDocument.Load()无法找到该文件。

我用一个try/catch在带有DataGrid的空WPF应用程序中对此进行了检查。

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
    } 

    private void DataGrid_Loaded(object sender, RoutedEventArgs e) 
    { 
     XDocument getElement = null;// = XDocument.Load(@"c:\dev\stackoverflow\DataGridWpf\DataGridWpf\details.xml"); 
     try 
     { 
      getElement = XDocument.Load(@"details.xml"); 
     } catch (Exception ex) { 
      var test = ex.ToString(); 
     } 

     // Create your List of ColumnNames outside the foreach to use later 
     var items = new List<ColumnNames>(); 

     foreach (var npc in getElement.Descendants("user")) 
     { 
      string id = npc.Attribute("id").Value; 
      string Name = npc.Attribute("Name").Value; 
      string Surname = npc.Attribute("Surname").Value; 
      string Computer = npc.Attribute("Computer").Value; 

      // You are adding an item to the existing List<ColumnNames> now, not a new one each time 
      items.Add(new ColumnNames(id, Name, Surname, Computer)); 
     } 

     // Finally, get a reference to the grid and set the ItemsSource property to use 
     // your full list containing all the items 
     var grid = sender as DataGrid; 
     grid.ItemsSource = items; 
    } 

此代码,如果你单步,将引发FileNotFound例外,如果未处理刚刚去世这和你结束了一个空的窗口!

在我的情况的完整路径的伎俩和电网很好地加载了:

enter image description here

+0

感谢您的回复,我真的很感谢回复,它对我的​​帮助非常大,虽然现在datagrid中没有任何结果。 –

+0

要么你复制了一些错误的代码,还有另一个问题;像现在这样用新代码更新你的问题,我们会看看我们是否可以把它整理出来。 –

+0

是的,这一切似乎都是正确的。 –

0

拉里墙,Perl中的作者,描述懒惰是1厚德载物一个程序员。不要做比你需要的更多的工作(有人将不得不维护它......也可能是你)。所以...

你为什么不使用XML序列化属性装点你的数据结构,是这样的:

[XmlRoot("info")] 
public class InfoList 
{ 

    [XmlElement("user")] 
    public User[] Users { get ; set ; } 

    public class User 
    { 
    [XmlAttribute] public string id  { get; set; } 
    [XmlAttribute] public string Name  { get; set; } 
    [XmlAttribute] public string Surname { get; set; } 
    [XmlAttribute] public string Computer { get; set; } 
    } 

} 

包裹反序列化的方法:

static User[] LoadUserDetails() 
{ 
    XmlSerializer serializer = new XmlSerializer(typeof(InfoList)) ; 
    using (Stream s = File.Open("details.xml",FileMode.Open,FileAccess.Read,FileShare.Read)) 
    { 
     InfoList instance = (InfoList) serializer.Deserialize(s) ; 
     return instance.Users ; 
    } 
} 

然后你的方法看起来是这样的:

private void DataGrid_Loaded(object sender, RoutedEventArgs e) 
{ 
    DataGrid grid = (DataGrid) sender ; 
    grid.ItemsSource = LoadUserDetails() ; 
    return ; 
} 

哪个更容易测试和/或维护?

+0

我对名称空间感到困惑I我的意思是进口。我已经使用System.Xml.Linq导入;使用System.Xml;使用System.Xml.Serialization;使用System.IO; –

+0

@FarbodD - 你所需要的基于属性的XML序列化应该是'System.Xml.Serialization',并且可能'System.Xml',这取决于你在做什么。 –