C# 如何用包含从XML节点读取器解析的XML数据的C列表填充DataGrid?
我通过读取XML文件并将基于每个节点的数据存储到一个对象中来收集XML文件中的数据 我想用我的工作列表中的数据填充我的DataGrid,但我不确定我做错了什么 动态构建表并添加数据。 手动构建XMLC# 如何用包含从XML节点读取器解析的XML数据的C列表填充DataGrid?,c#,.net,xml,wpf,datagrid,C#,.net,Xml,Wpf,Datagrid,我通过读取XML文件并将基于每个节点的数据存储到一个对象中来收集XML文件中的数据 我想用我的工作列表中的数据填充我的DataGrid,但我不确定我做错了什么 动态构建表并添加数据。 手动构建XML public partial class amgrid : Window { public static Configuration AppSettings { get; set; } JobList job = new JobList();
public partial class amgrid : Window
{
public static Configuration AppSettings { get; set; }
JobList job = new JobList();
public amgrid()
{
InitializeComponent();
XmlDocument doc = new XmlDocument();
string docPath = @"C:\Users\contract_lshamoon\Desktop\arm\arm\arm\xmldb.xml";
doc.Load(docPath);
XmlElement root = doc.DocumentElement;
XmlNodeList elemList = root.GetElementsByTagName("Jobs");
findAllNodes(root);
doc.Save(@"C:\Users\contract_lshamoon\Desktop\arm\arm\arm\xmldb.xml");
DG.DataContext = job;
}
int index = 0;
public void findAllNodes(XmlNode node)
{
index++;
foreach (XmlNode n in node)
findAllNodes(n);
if (node.Name == "Job")
{
job.Job = index.ToString();
Console.WriteLine();
Console.WriteLine("job.Job" + " : " + index + " : " + job.Job);
}
if (node.Name == "JobDate")
{
job.JobDate = node.InnerText;
Console.WriteLine("Job.JobDate" + " : " + job.JobDate);
}
if (node.Name == "File")
{
job.File = node.InnerText;
Console.WriteLine("Job.File" + " : " + job.File);
}
if (node.Name == "FilePath")
{
job.FilePath = node.InnerText;
Console.WriteLine("Job.FilePath" + " : " + job.FilePath);
}
if (node.Name == "Extension")
{
job.Extension = node.InnerText;
Console.WriteLine("Job.Extension" + " : " + job.Extension);
}
if (node.Name == "Age")
{
job.Age = node.InnerText;
Console.WriteLine("Job.Age" + " : " + job.Age);
}
if (node.Name == "JobComment")
{
job.JobComment = node.InnerText;
Console.WriteLine("Job.JobComment" + " : " + job.JobComment);
}
}
private List<JobList> LoadCollectionData()
{
List<JobList> jobList = new List<JobList>();
jobList.Add(new JobList()
{
Job = job.Job,
JobDate = job.JobDate,
FilePath = job.FilePath,
Extension = job.Extension,
Age = job.Age,
JobComment = job.JobComment
});
return jobList;
}
}
public class JobList
{
[XmlAttribute("JobId")]
public string Job { get; set; }
[XmlElement("JobDate")]
public string JobDate { get; set; }
[XmlElement("File")]
public string File { get; set; }
[XmlElement("FilePath")]
public string FilePath { get; set; }
[XmlElement("Extension")]
public string Extension { get; set; }
[XmlElement("Age")]
public string Age { get; set; }
[XmlElement("JobComment")]
public string JobComment { get; set; }
}
我只想让每一行都显示每个列表项。作业类型JobList不是其类型所暗示的列表。它只包含单个作业的属性。您只有该类的一个实例,它被分配给job。每次遇到节点时,都会修改该实例的属性
当您尝试DB.Items.Addjob;,您正在将同一个实例添加到网格的项目列表中,因此它自然会显示该项目N次。此外,它将是指定给这些属性的值的累积结果,即写入每个属性的最后一个值
如果我正确理解了您的结构,这是很困难的,因为您还并没有展示XML的示例,那个么您正在导航XML节点,并平等地对待所有节点类型,包括元素和属性。例如,如果您只有两个元素,其中一个元素只有JobDate属性,另一个元素只有FilePath属性,则job最终将分配这两个属性,并且两行都将显示这两个值。它不会显示具有一个值的一行和具有另一个值的另一行,因为您没有处于这些状态的实例
另一个问题是,您没有理解元素应该映射到作业列表实例,属性应该映射到该实例的属性。findAllNodes可以说是遍历XML节点的一个好算法,但是如果不以不同的方式处理节点类型,它就不能实现加载数据的目的。具体来说,在某些节点类型中,需要实例化作业列表,而在其他节点类型中,需要为其属性赋值。XML序列化在这里是一个更好的选择,因为它将为您完成所有这些。您甚至可以在属性中为其设置属性,所以请直接使用它
您也有一个名为LoadCollectionData的方法,但您从未调用过它,或者至少没有显示您在任何地方调用过它。该方法确实返回一个项目列表,但它向其中添加了您创建的唯一一个JobList实例,即您的job字段中的实例
如果删除“作业”字段,则读取“作业列表作业=新作业列表;”的行;,您将在使用该实例的地方开始出现错误。这将破坏您的代码,但希望它也能告诉您应该在哪里创建新实例或接受实例作为参数
其他一些审查说明:
您正在将XML文档保存回磁盘,而不进行修改。您可以安全地删除对doc.Save的调用。
在构造函数中加载数据可能不是一个好主意。现在,我不是WPF专家,我甚至不在电视上播放WPF,但你应该寻找一个加载事件来处理或类似的事情。最终,您将希望使用异步,以便您的UI在加载时能够响应。
一般来说,在需要变量之前不要声明它。当您声明一个变量并让它腐烂直到使用它时,您会允许自己在执行序列中出错,这可能会导致在您忘记尚未初始化它时出现NullReferenceException之类的情况。不要把它提升到一个领域,直到你知道它必须是一个领域。
就答案而言,我只能说这么多了,因为您提供的代码有点迂回,您的意图也不完全清楚。我祝你在应用上述信息时好运
public class JobList
{
[XmlElement("Job")]
public string Job { get; set; }
[XmlElement("JobDate")]
public string JobDate { get; set; }
[XmlElement("File")]
public string File { get; set; }
[XmlElement("FilePath")]
public string FilePath { get; set; }
[XmlElement("Extension")]
public string Extension { get; set; }
[XmlElement("Age")]
public string c { get; set; }
[XmlElement("JobComment")]
public string JobComment { get; set; }
}
public partial class amgrid : Window
{
public amgrid()
{
InitializeComponent();
XmlDocument doc = new XmlDocument();
string docPath = @"C:\Users\contract_lshamoon\Desktop\arm\arm\arm\xmldb.xml";
doc.Load(docPath);
XmlElement root = doc.DocumentElement;
XmlNodeList elemList = root.GetElementsByTagName("Jobs");
findAllNodes(root);
doc.Save(@"C:\Users\contract_lshamoon\Desktop\arm\arm\arm\xmldb.xml");
}
public void findAllNodes(XmlNode node)
{
foreach (XmlNode n in node)
{
JobList jobs = new JobList();
string job = n.Attributes["JobId"].Value;
string date = n.FirstChild.InnerText;
string file = n.FirstChild.NextSibling.InnerText;
string path = n.FirstChild.NextSibling.NextSibling.InnerText;
string extension = n.FirstChild.NextSibling.NextSibling.NextSibling.InnerText;
string age = n.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling.InnerText;
string comment = n.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText;
jobs.Job = job;
jobs.JobDate = date;
jobs.File = file;
jobs.FilePath = path;
jobs.Extension = extension;
jobs.c = age;
jobs.JobComment = comment;
DG.DataContext = jobs;
DG.Items.Add(jobs);
}
}
}
你从不在工作列表中填写任何内容。我提供了一个空白示例…我尝试过:DG.Items.Addjobs;但这让每一行都充满了同样的工作。谢谢!这太棒了!我要试试这个!对C来说还是有点新鲜!
public class JobList
{
[XmlElement("Job")]
public string Job { get; set; }
[XmlElement("JobDate")]
public string JobDate { get; set; }
[XmlElement("File")]
public string File { get; set; }
[XmlElement("FilePath")]
public string FilePath { get; set; }
[XmlElement("Extension")]
public string Extension { get; set; }
[XmlElement("Age")]
public string c { get; set; }
[XmlElement("JobComment")]
public string JobComment { get; set; }
}
public partial class amgrid : Window
{
public amgrid()
{
InitializeComponent();
XmlDocument doc = new XmlDocument();
string docPath = @"C:\Users\contract_lshamoon\Desktop\arm\arm\arm\xmldb.xml";
doc.Load(docPath);
XmlElement root = doc.DocumentElement;
XmlNodeList elemList = root.GetElementsByTagName("Jobs");
findAllNodes(root);
doc.Save(@"C:\Users\contract_lshamoon\Desktop\arm\arm\arm\xmldb.xml");
}
public void findAllNodes(XmlNode node)
{
foreach (XmlNode n in node)
{
JobList jobs = new JobList();
string job = n.Attributes["JobId"].Value;
string date = n.FirstChild.InnerText;
string file = n.FirstChild.NextSibling.InnerText;
string path = n.FirstChild.NextSibling.NextSibling.InnerText;
string extension = n.FirstChild.NextSibling.NextSibling.NextSibling.InnerText;
string age = n.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling.InnerText;
string comment = n.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText;
jobs.Job = job;
jobs.JobDate = date;
jobs.File = file;
jobs.FilePath = path;
jobs.Extension = extension;
jobs.c = age;
jobs.JobComment = comment;
DG.DataContext = jobs;
DG.Items.Add(jobs);
}
}
}
<DataGrid x:Name="DG">
<DataGrid.DataContext>
<local:JobList/>
</DataGrid.DataContext>
<DataGrid.Columns>
<DataGridTextColumn x:Name="JobCol" Binding="{Binding Job}" Header="Job"/>
<DataGridTextColumn x:Name="JobDateCol" Binding="{Binding JobDate}" Header="Date"/>
<DataGridTextColumn x:Name="FilePathCol" Binding="{Binding FilePath}" Header="Path"/>
<DataGridTextColumn x:Name="ExtensionCol" Binding="{Binding Extension}" Header="Extension"/>
<DataGridTextColumn x:Name="AgeCol" Binding="{Binding Age}" Header="Age"/>
<DataGridTextColumn x:Name="JobCommentCol" Binding="{Binding JobComment}" Header="Comment"/>
</DataGrid.Columns>
</DataGrid>