C# 如何用包含从XML节点读取器解析的XML数据的C列表填充DataGrid?

C# 如何用包含从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();

我通过读取XML文件并将基于每个节点的数据存储到一个对象中来收集XML文件中的数据

我想用我的工作列表中的数据填充我的DataGrid,但我不确定我做错了什么

动态构建表并添加数据。 手动构建XML

    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>