Matching XML elements to ListBox selected item - C#

久未见 提交于 2019-12-11 11:19:23

问题


I want to make it so the item I have selected in the list box shows its sibling elements in labels. Currently I used my XML file to get the <Name> element and populate my list box with these <Name> values. Now I want to make it so that whenever the <Name> is highlighted in the list box, it will show the <Code> related to that module in a label on the form.

i.e. If in the List Box, Algorithms and Data Structures is selected, show its Code,Capacity,Semester and Prerequisites in labels on the form. If some other module is selected, do that again for the selected module

Here is my 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>

And here is how I've tried to achieve what I need:

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();
            }

        }

Please if someone could help me I would appreciate it


回答1:


I would go back a couple of steps and look at your design. How often will you be accessing the XML directly in your code? Reading a file each time the ListBox selected index changes seems to be a waste, not to mention if the file is not accessible, it will throw an exception.

If you are going to be accessing the XML numerous times, I would consider is creating an object to hold your XML data:

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; }
}

Then create a collection of your Module objects when you read the XML

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);

(if the name elements won't be unique you can't do a dictionary and you'll have to do a list)

From that collection, you can then load the names into the listBox

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

And then in your listBox1_SelectedIndexChanged event handler you can do sometihng like:

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

You can also consider DataBinding the Module object to the ListBox, but I am not very savvy with it, so I can't offer much help there.

Edit: Here's how to put the collection in your code so you can access it any method.

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);            
    }


}



回答2:


I think this will do what you want:

    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;
    } 

This will fix your problem, but it's still bad code. You shouldn't read the whole file every time the index is changed. See below for a better solution.

Alternative (better) solution:

Create a class Module with all properties of a module. Populate a list of Module objects from the XML file and set this as the data source for the list box. ListBox has a DisplayMember property that you can set to the name of the property you want to show in the ListBox e.g. "Name". If you do it like this then the SelectedValue property will be an instance of Module and you can access its properties directly.



来源:https://stackoverflow.com/questions/9955609/matching-xml-elements-to-listbox-selected-item-c-sharp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!