2012-03-31 6 views
1

Ich möchte es so machen, dass das Element, das ich im Listenfeld ausgewählt habe, seine Geschwisterelemente in Beschriftungen anzeigt. Zur Zeit habe ich meine XML-Datei verwendet, um das Element <Name> zu erhalten und meine Listbox mit diesen <Name> Werten zu füllen. Jetzt möchte ich es so machen, dass, immer wenn das <Name> im Listenfeld hervorgehoben wird, es die <Code> bezogen auf das Modul in einem Etikett auf dem Formular zeigt.Übereinstimmende XML-Elemente zu ListBox ausgewähltem Element - C#

Wenn in der Listbox Algorithmen und Datenstrukturen ausgewählt ist, werden Code, Kapazität, Semester und Voraussetzungen in Beschriftungen des Formulars angezeigt. Wenn ein anderes Modul gewählt ist, das wieder tun für das ausgewählte Modul

Hier ist meine 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> 

Und hier ist, wie ich habe versucht zu erreichen, was ich brauche:

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

     } 

Bitte, wenn mir jemand helfen könnte, würde ich es zu schätzen wissen

Antwort

4

Ich würde ein paar Schritte zurückgehen und Ihr Design betrachten. Wie oft greifen Sie direkt auf den XML-Code in Ihrem Code zu? Das Lesen einer Datei jedes Mal, wenn die ListBox Indexänderungen auswählt, scheint eine Verschwendung zu sein, ganz zu schweigen davon, wenn die Datei nicht zugänglich ist, wird eine Ausnahme ausgelöst.

Wenn Sie die XML mehrmals zu gehen, den Zugriff, würde ich prüfen, ist ein Objekt erstellt die XML-Daten zu halten:

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

Dann eine Sammlung Ihrer Module-Objekte erstellen, wenn Sie die XML lesen

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

(wenn die Namenselemente nicht eindeutig sein, Sie können ein Wörterbuch nicht tun, und Sie werden eine Liste zu tun haben)

Aus dieser Sammlung können Sie dann laden t er Namen in die ListBox

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

Und dann in Ihren listBox1_SelectedIndexChanged Event-Handler können Sie tun sometihng wie:

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

Sie können auch prüfen, das Module Objekt an den ListBox Datenbindung, aber ich bin nicht sehr versiert damit kann ich nicht viel Hilfe anbieten.

Bearbeiten: Hier ist, wie Sie die Sammlung in Ihrem Code, so dass Sie auf jede Methode zugreifen können.

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


} 
+0

Können Sie mir sagen, wo ich die Sammlung in meinen Code einfügen soll? Ich weiß nicht, wo – a7omiton

+0

Dies ist die alternative Lösung, über die ich unten gesprochen habe. Anstatt jedoch ein Wörterbuch zu verwenden, können Sie die Modulliste direkt der ListBox zuweisen und dann die DisplayMember-Eigenschaft festlegen. – aKzenT

+0

Sie sollten angeben, ob Sie gerade Ihre Listenbox füllen. – aKzenT

3

ich denke, das tun, was Sie wollen:

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

Dies wird Ihr Problem beheben, aber es ist immer noch schlechter Code. Sie sollten die gesamte Datei nicht jedes Mal lesen, wenn der Index geändert wird. Siehe unten für eine bessere Lösung.

Alternative (besser) Lösung:

Erstellen Sie eine Klasse Module mit allen Eigenschaften eines Moduls. Füllen Sie eine Liste der Module-Objekte aus der XML-Datei aus und legen Sie diese als Datenquelle für das Listenfeld fest. ListBox verfügt über eine DisplayMember-Eigenschaft, die Sie auf den Namen der Eigenschaft festlegen können, die in der ListBox z. "Name". Wenn Sie es so machen, wird die SelectedValue Eigenschaft eine Instanz von Module sein und Sie können direkt auf seine Eigenschaften zugreifen.

+0

Ich erhalte einen Fehler bei Zeichenfolge name = listBox1.SelectedValue; Sprichwort kann nicht vom Typ Objekt in String konvertieren – a7omiton

+0

Mein Fehler. Siehe die aktualisierte Lösung (Call ToString on SelectedValue) – aKzenT

+0

Siehe auch die alternative Lösung. In jedem Fall sollten Sie XDocument.Load aus der Funktion entfernen und in einer Klassenvariablen speichern, damit Sie nicht jedes Mal die gesamte Datei lesen, wenn sich der Index ändert. – aKzenT

Verwandte Themen