2014-01-29 63 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',這取決於你在做什麼。 –