2012-02-07 14 views
6

Esto carga un conjunto de valores de un archivo XML y los coloca en una clase para el almacenamiento. Estoy intentando descubrir cómo mostrar los valores como una lista para poder ubicarlos en un Listbox.Salida de clase de valores almacenados a la lista

Pensé que habría una manera fácil como un método .ToList() o para poder foreach a través de las cadenas en la clase (no pública GetEnumerator). Pude descubrir que Foreach oculta parte de la complejidad pero no de distancia para hacer lo que quiero.

He estado buscando en línea con el vano (que carece de la terminología correcta tal vez), por desgracia me fui de mi C# libros de referencia en el trabajo:/

apreciarían mucho un puntero en la dirección correcta, Gracias.

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.IO; 
using System.Xml; 

namespace ThereIsOnlyRules 
{ 
public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void Form1_Load(object sender, EventArgs e) 
    { 
     try 
     { 
      listBox1.Items.Clear(); 

      string path = "characterXML.xml"; 
      FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); 
      System.Xml.XmlDocument CXML = new System.Xml.XmlDocument(); 

      CXML.Load(fs); 

      //Get the number of elements 
      XmlNodeList elemList = CXML.GetElementsByTagName("unit"); 

      //foreach (var element in elemList) 
      //{ 
      // listBox1.Items.Add(element); 
      //} 

      for (int i = 0; i < elemList.Count; i++) 
      { 
       UnitAttributes attributes = new UnitAttributes(); 

       attributes.army = elemList[i].Attributes["army"].Value; 
       attributes.category = elemList[i].Attributes["category"].Value; 
       attributes.type = elemList[i].Attributes["type"].Value; 
       attributes.composition = elemList[i].Attributes["composition"].Value; 
       attributes.WS = elemList[i].Attributes["WS"].Value; 
       attributes.BS = elemList[i].Attributes["BS"].Value; 
       attributes.T = elemList[i].Attributes["T"].Value; 
       attributes.W = elemList[i].Attributes["W"].Value; 
       attributes.I = elemList[i].Attributes["I"].Value; 
       attributes.A = elemList[i].Attributes["A"].Value; 
       attributes.LD = elemList[i].Attributes["LD"].Value; 
       attributes.save = elemList[i].Attributes["Save"].Value; 
       attributes.armour = elemList[i].Attributes["armour"].Value; 
       attributes.weapons = elemList[i].Attributes["weapons"].Value; 
       attributes.specialrules = elemList[i].Attributes["specialrules"].Value; 
       attributes.transport = elemList[i].Attributes["transport"].Value; 
       attributes.options = elemList[i].Attributes["options"].Value; 

       //foreach (string item in attributes) 
       //{ 

        //unit.Add(item); 
       //} 
       //listBox1.Items.AddRange(attributes) 

      } 

      //Close the filestream 
      fs.Close(); 
     } 
     catch (Exception ex) 
     { 

     } 
    } 
} 
} 

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace ThereIsOnlyRules 
{ 
class UnitAttributes 
{ 
    public string army { get; set; } 
    public string category { get; set; } 
    public string type { get; set; } 
    public string composition { get; set; } 
    public string WS { get; set; } 
    public string BS { get; set; } 
    public string T { get; set; } 
    public string W { get; set; } 
    public string I { get; set; } 
    public string A { get; set; } 
    public string LD { get; set; } 
    public string save { get; set; } 
    public string armour { get; set; } 
    public string weapons { get; set; } 
    public string specialrules { get; set; } 
    public string transport { get; set; } 
    public string options { get; set; } 
    } 
} 

<?xml version="1.0"?> 
<config> 
<unit 
army="Tyranids" 
category="Troops" 
type="Infantry" 
composition="10-30" 
WS="3" 
BS="3" 
T="3" 
W="1" 
I="4" 
A="1" 
LD="6" 
Save="6+" 
armour="Chitin" 
weapons="Claws and Teeth, Fleshborer" 
specialrules="Instictive Behaviour - Lurk, Move Through Cover" 
transport="If the brood consists of 20 models or less, it may take a Mycetic Spore." 
options="Strangleweb, Spinefists, Spike rifle, Devourer, Adrenal Glands, Toxin Sacs" 
> 
Termagant Brood 
</unit> 
<unit 
army="Tyranids" 
category="Troops" 
type="Infantry" 
composition="10-30" 
WS="3" 
BS="3" 
T="3" 
W="1" 
I="5" 
A="2" 
LD="6" 
Save="6+" 
armour="Chitin" 
weapons="Scything Talons" 
specialrules="Instictive Behaviour - Feed, Bounding Leap, Fleet, Move Through Cover" 
transport="If the brood consists of 20 models or less, it may take a Mycetic Spore." 
options="Adrenal Glands, Toxin Sacs" 
> 
Hormagaunt Brood 
</unit> 
</config> 
+1

'XmlNodeList' implementa' IEnumerable', por lo que su 'foreach' debería funcionar. – svick

Respuesta

3

¿Son los miembros de sus campos de clase o propiedades? De cualquier manera, un pequeño reflejo y Linq deberían permitirle enumerar a través de los miembros de datos de su clase, después de haber hidratado una instancia de la misma desde su archivo XML.

var fieldDictionary = 
    (from f in typeof(UnitAttributes).GetFields() 
    select new {Name = f.Name, Value = (string)(f.GetValue(attributes))}) 
    .ToDictionary(x=>x.Name, x=>x.Value); 

fieldDictionary es ahora un Dictionary<string, string> (que es un IEnumerable<KeyValuePair<string, string>>), que debería ser adecuado para cargar en un ListBox.

Tenga en cuenta; la reflexión es lenta. Sería mucho más preferible que modifique o amplíe su clase UnitAttributes para implementar IEnumerable (probablemente una Tuple, quizás una KeyValuePair). También le permitirá enumerar las propiedades de una instancia de la clase exactamente en el orden que desee, en lugar del orden en el que están definidas, o mediante otros datos de FieldInfo/PropertyInfo, como el nombre del campo.

También tenga en cuenta que un campo no es una propiedad, y viceversa. Si tiene una combinación de propiedades y campos públicos en su clase, recomiendo encarecidamente la estandarización de uno o el otro; de lo contrario, deberá reflejar AMBAS, una lista de propiedades y una lista de campos utilizando dos de las afirmaciones de Linq anteriores (a un costo de aproximadamente el doble del tiempo de ejecución), y no habrá posibilidad de que se encuentren en ninguna definición personalizada. orden.

2

se ahorrará mucho tiempo y esfuerzo si se utiliza un serializador común como XmlSerializer para manejar la conversión de sus objetos a/de las cadenas. No tiene que escribir este tipo de código desde cero.

+0

De acuerdo, pero creo que el quid de la cuestión es cómo enumerar a través de los datos en forma de objeto, no en XML. – KeithS

+0

Todavía aprecio que me digan, solo estaría leyendo algo similar en otro lado. – Amicable

Cuestiones relacionadas