C# XML Datagrid根元素-foreach循环
我想将我的所有信息从XML获取到Datagrid 目前我有:C# XML Datagrid根元素-foreach循环,c#,xml,wpf,linq,datagrid,C#,Xml,Wpf,Linq,Datagrid,我想将我的所有信息从XML获取到Datagrid 目前我有: 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,
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;
}
}
我说了一个错误
无法使用“非发票成员”System.Xml.Linq.XDocument.Root”
就像一种方法。”
我不知道我如何才能使这项工作,这是相当长的一段时间,我一直在试图得到修复,一些帮助与友好。谢谢
更新: 这是大卫慷慨帮助我之后的新代码。尽管它仍然不起作用
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 ColmNames outside the foreach to use later
var items = new List<ColumnNames>();
foreach (var npc in getElement.Root.Elements("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;
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;
}
private void DataGrid\u已加载(对象发送方,RoutedEventArgs e)
{
//getElement是此对象的奇怪名称:)
XDocument getElement=XDocument.Load(“details.xml”);
//在foreach之外创建ColmNames列表以供以后使用
var items=新列表();
foreach(getElement.Root.Elements(“用户”)中的var npc)
{
字符串id=npc.Attribute(“id”).Value;
字符串名称=npc.Attribute(“Name”).Value;
字符串姓氏=npc.Attribute(“姓氏”).Value;
字符串Computer=npc.Attribute(“Computer”).Value;
添加(新列名(id、姓名、姓氏、计算机));
}
//最后,获取对网格的引用并设置要使用的ItemsSource属性
//包含所有项目的完整列表
var grid=发送方作为数据网格;
grid.ItemsSource=项目;
}
你很接近
foreach (var npc in getElement.Descendants("user"))
对于给定的XML结构,它确实有效,并且是正确的。不过,请参见我答案的底部,了解一个重要的区别
问题是您正在设置grid.ItemsSource=items
在您的foreach
循环中,因此每次foreach循环时只添加一个项,并且您总是只得到数据网格中的最后一个项
此外,您还需要保留foreach
循环之外的项目列表,否则它只存在于foreach
中(仅具有范围)
要解决这个问题,您需要移动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 (var npc in getElement.Descendants("user"))
这里的主要区别是。后代()
将获得名为“user”的任何节点,无论其嵌套深度如何.Elements()
将只从当前节点(直接子节点)获取下一级
因此,尽管XML结构的工作原理似乎相同,但在XML结构发生变化(或场景/项目不同等)时,理解这种区别是很重要的
作为旁注,getElement是XDocument
对象的奇怪名称;我通常只使用xDoc之类的东西
再更新一次-为什么不起作用?
当我意识到这是一个WPF数据网格,并且您正在加载一个本地XML文件时,我突然意识到您的网格没有显示任何内容,因为XDocument.Load()无法找到该文件
我在一个带有DataGrid的空WPF应用程序中用try/catch检查了这一点
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;
}
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
}
已加载私有void数据网格(对象发送方,RoutedEventArgs e)
{
XDocument getElement=null;/=XDocument.Load(@“c:\dev\stackoverflow\DataGridWpf\DataGridWpf\details.xml”);
尝试
{
getElement=XDocument.Load(@“details.xml”);
}捕获(例外情况除外){
var测试=例如ToString();
}
//在foreach之外创建列名列表,以便以后使用
var items=新列表();
foreach(getElement.subjections(“用户”)中的var npc)
{
字符串id=npc.Attribute(“id”).Value;
字符串名称=npc.Attribute(“Name”).Value;
字符串姓氏=npc.Attribute(“姓氏”).Value;
字符串Computer=npc.Attribute(“Computer”).Value;
//您现在正在将一个项目添加到现有列表中,而不是每次添加一个新项目
添加(新列名(id、姓名、姓氏、计算机));
}
//最后,获取对网格的引用并设置要使用的ItemsSource属性
//包含所有项目的完整列表
var grid=发送方作为数据网格;
grid.ItemsSource=项目;
}
如果您单步执行,这段代码将抛出FileNotFound异常,如果未经处理,该异常将消失,您将得到一个空窗口
在我的例子中,完整路径起到了作用,网格很好地加载:
Perl的作者拉里·沃尔(Larry Wall)将懒惰描述为程序员的第一大美德。不要做超出你需要的工作(有人将不得不维护它……可能就是你)。因此
为什么不用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; }
}
}
private void DataGrid_Loaded(object sender, RoutedEventArgs e)
{
DataGrid grid = (DataGrid) sender ;
grid.ItemsSource = LoadUserDetails() ;
return ;
}
将反序列化包装到方法中:
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 ;
}
}
然后,您的方法看起来像:
[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; }
}
}
private void DataGrid_Loaded(object sender, RoutedEventArgs e)
{
DataGrid grid = (DataGrid) sender ;
grid.ItemsSource = LoadUserDetails() ;
return ;
}
哪个更容易测试和/或维护?感谢您的回复,我非常感谢您的回复,虽然现在datagrid中没有结果,但它对我帮助很大。要么是您复制了一些错误的代码,要么是出现了另一个问题;请用您现在的新代码更新您的问题,我们将看看是否可以解决它。请稍候,我发现了问题他的问题是XML加载本身。我已经尝试了完整路径和npc.XML,有什么问题吗?让我们看看你确定DataBind()吗正在调用..您是否已通过调试器并正在执行此代码。我觉得代码看起来不错。它只通过一次,但其余部分不会通过。通过什么一次,foreach循环?1.确保您的XML文件正确。2.确保正确重建解决方案并运行新代码。我明白了ting混淆了我要导入的名称空间。我使用System.Xml.Linq;使用System.Xml;使用System.Xml.Serialization;使用System.I导入
private void DataGrid_Loaded(object sender, RoutedEventArgs e)
{
DataGrid grid = (DataGrid) sender ;
grid.ItemsSource = LoadUserDetails() ;
return ;
}