将XML元素匹配到ListBox所选项 - C#

时间:2012-03-31 11:51:20

标签: c# xml winforms linq linq-to-xml

我想这样做,因此我在列表框中选择的项目会在标签中显示其兄弟元素。目前,我使用我的XML文件获取<Name>元素,并使用这些<Name>值填充我的列表框。现在我想这样做,以便只要在列表框中突出显示<Name>,它就会在表单上的标签中显示与该模块相关的<Code>

即。如果在列表框中选择了算法和数据结构,则在表单上的标签中显示其代码,容量,学期和先决条件。如果选择了其他模块,请对所选模块再次执行此操作

这是我的XML:

    <?xml version="1.0" encoding="utf-8" ?>
<SoftwareEngineering>
  <Module>
    <Name>Algorithms and Data Structures</Name>
    <Code>3SFE504</Code>
    <Capacity>5</Capacity>
    <Semester>1</Semester>
    <Prerequisite>none</Prerequisite>
  </Module>
  <Module>
    <Name>3D Graphics I</Name>
    <Code>3SFE508</Code>
    <Capacity>5</Capacity>
    <Semester>1</Semester>
    <Prerequisite>none</Prerequisite>
  </Module>
  <Module>
    <Name>Event-Driven Programming</Name>
    <Code>3SFE513</Code>
    <Capacity>10</Capacity>
    <Semester>1</Semester>
    <Prerequisite>none</Prerequisite>
  </Module>
  <Module>
    <Name>Object Oriented Design</Name>
    <Code>3SFE514</Code>
    <Capcity>10</Capcity>
    <Semester>1</Semester>
    <Prerequisite>none</Prerequisite>
  </Module>
  <Module>
    <Name>Requirements Engineering</Name>
    <Code>3SFE516</Code>
    <Capacity>10</Capacity>
    <Semester>1</Semester>
    <Prerequisite>none</Prerequisite>
  </Module>
  <Module>
    <Name>Introduction to AI</Name>
    <Code>3SFE599</Code>
    <Capacity>5</Capacity>
    <Semester>1</Semester>
    <Prerequisite>none</Prerequisite>
  </Module>
  <Module>
    <Name>Java Mobile Application Development</Name>
    <Code>3SFE540</Code>
    <Capacity>5</Capacity>
    <Semester>1</Semester>
    <Prerequisite>3SFE514(corequisite)</Prerequisite>
  </Module>
  <Module>
    <Name>C# .NET Programming</Name>
    <Code>3SFE541</Code>
    <Capacity>5</Capacity>
    <Semester>1</Semester>
    <Prerequisite>3SFE514(corequisite)</Prerequisite>
  </Module>
  <Module>
    <Name>Software Engineering Group Project</Name>
    <Code>3SFE515</Code>
    <Capacity>5</Capacity>
    <Semester>2</Semester>
    <Prerequisite>3SFE514(corequisite)</Prerequisite>
  </Module>
  <Module>
    <Name>Software Engineering</Name>
    <Code>3SFE519</Code>
    <Capacity>10</Capacity>
    <Semester>2</Semester>
    <Prerequisite>none</Prerequisite>
  </Module>
  <Module>
    <Name>Mobile User Interface Development</Name>
    <Code>3SFE542</Code>
    <Capacity>5</Capacity>
    <Semester>2</Semester>
    <Prerequisite>3SFE540</Prerequisite>
  </Module>
  <Module>
    <Name>Interactive Multimedia</Name>
    <Code>3MTS954</Code>
    <Capacity>5</Capacity>
    <Semester>2</Semester>
    <Prerequisite>none</Prerequisite>
  </Module>
  <Module>
    <Name>Concurrent Programming</Name>
    <Code>3SFE555</Code>
    <Capacity>5</Capacity>
    <Semester>2</Semester>
    <Prerequisite>none</Prerequisite>
  </Module>
  <Module>
    <Name>Mobile Gaming</Name>
    <Code>3SFE557</Code>
    <Capacity>10</Capacity>
    <Semester>2</Semester>
    <Prerequisite>none</Prerequisite>
  </Module>
  <Module>
    <Name>Intelligent Systems</Name>
    <Code>3SFE500</Code>
    <Capacity>10</Capacity>
    <Semester>2</Semester>
    <Prerequisite>3SFE599</Prerequisite>
  </Module>
  <Module>
    <Name>3D Graphics II</Name>
    <Code>3SFE501</Code>
    <Capacity>10</Capacity>
    <Semester>2</Semester>
    <Prerequisite>3SFE508</Prerequisite>
  </Module>
</SoftwareEngineering>

以下是我试图达到我需要的方式:

private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            XDocument doc = XDocument.Load(workingDir + @"\Moduleslist.xml");
            var names = doc.Root.Descendants("Module").Elements("Code").Select(b => b.Value);
            var name = doc.Root.Descendants("Module").Elements("Name").Select(a => a.Value);

            if (listBox1.SelectedValue == name)
            {
                labelCodeNumber.Text = names.ToString();
            }

        }

如果有人可以帮助我,我会很感激

2 个答案:

答案 0 :(得分:4)

我会回过头来看看你的设计。您多久会直接在代码中访问XML?每次ListBox选择索引更改时读取文件似乎都是浪费,更不用说如果文件不可访问,它将引发异常。

如果您要多次访问XML,我会考虑创建一个保存XML数据的对象:

public class Module
{
    public String Name { get; set; }
    public String Code { get; set; }
    public String Capacity { get; set; }
    public String Semester { get; set; }
    public String Prerequisite { get; set; }
}

然后在阅读XML时创建Module对象的集合

var modules = (from elem in doc.Root.Descendants("Module")
               select new Module()
               {
                   Name = elem.Element("Name").Value, 
                   Code = elem.Element("Code").Value, 
                   Capacity = elem.Element("Capacity").Value, 
                   Semester = elem.Element("Semester").Value, 
                   Prerequisite = elem.Element("Prerequisite").Value, 
               }).ToDictionary(k=>k.Name,v=>v);

(如果名称元素不是唯一的,你就不能做字典而你必须做一个清单)

然后,您可以从该集合中将名称加载到listBox

listBox1.Items.AddRange(modules.Keys.ToArray());

然后在你的listBox1_SelectedIndexChanged事件处理程序中,您可以执行以下操作:

private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
    labelCodeNumber.Text = modules[listBox1.SelectedValue].Code;
}

您也可以考虑将Module对象的DataBinding绑定到ListBox,但我对它并不十分精明,所以我无法在那里提供太多帮助。

编辑: 以下是如何将集合放入代码中,以便您可以通过任何方法访问它。

public partial class Form1 : Form
{
    private Dictionary<String, Module> modules;

    public Form1()
    {
        this.modules = LoadXml(XDocument.Load(xmlPath);
    }

    private Dictionary<String, Module> LoadXml(XDocument doc)
    {
        return (from elem in doc.Root.Descendants("Module")
                       select new Module()
                       {
                           Name = elem.Element("Name").Value, 
                           Code = elem.Element("Code").Value, 
                           Capacity = elem.Element("Capacity").Value, 
                           Semester = elem.Element("Semester").Value, 
                           Prerequisite = elem.Element("Prerequisite").Value, 
                       }).ToDictionary(k=>k.Name, v=>v);            
    }


}

答案 1 :(得分:3)

我认为这会做你想做的事情:

    XDocument doc = XDocument.Load(Path.Combine(workingDir, @"Moduleslist.xml"));

    private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
    {
        string name = listBox1.SelectedValue.ToString();
        var propertiesFromName = (from module in doc.Root.Descendants("Module")
                                 where module.Element("Name").Value == name
                                 select new {Code = module.Element("Code").Value}).First();

        labelCodeNumber.Text = propertiesFromName.Code;
    } 

这将解决您的问题,但它仍然是错误的代码。每次更改索引时,您都不应该读取整个文件。请参阅下文以获得更好的解决方案。

替代(更好)解决方案:

使用模块的所有属性创建一个类Module。从XML文件填充Module对象列表,并将其设置为列表框的数据源。 ListBox具有DisplayMember属性,您可以将其设置为要在ListBox中显示的媒体资源的名称,例如&#34;名称&#34 ;.如果您这样做,那么SelectedValue属性将是Module的实例,您可以直接访问其属性。