A készítendő alkalmazás alkalmas XML állományok megjelenítésére egy TreeView kontrolban. A programban annak indulásakor feltöltünk véletlen adatokkal egy DataSet objektumot, amelynek tartalmát egy XML állományba írjuk, elkészítve az első olvasható, szabványos próba XML állományunkat.
A DataSet objektumban tárolt adattábla tartalmaz két oszlopot, melyek nem levelekként jelennek meg az XML-fán, hanem megjelenés specifikus információt hordoznak arra vonatkozóan, hogy milyen képállomány jelenjen meg az egyes levelek csomópontján a TreeView kontrolban.
Ismert ugyanis, hogy a TreeView kontrol ImageList property-jében tárolhatunk egy ImageList objektumot, mely nem más, mint egy képállomány lista, ahol a lista elemeire sorszámokkal hivatkozhatunk.
Az ilyen információt hordozó oszlopot a következőképpen deklaráljuk annak érdekében, hogy XmlAttribute objektumként tárolódjon az XML állományban:
...
DataColumn dc4 = new DataColumn("IMAGE_INDEX_HEAD", Type.GetType("System.String"),"",MappingType.Attribute);
DataColumn dc5 = new DataColumn("IMAGE_INDEX_VALUE", Type.GetType("System.String"),"",MappingType.Attribute);
Az oszlopok konstruktorát a MappingType.Attribute értékkel paraméterezzük, amely lehetővé teszi egy név=”érték” pár beépülését az XML-be.
<Products IMAGE_INDEX_HEAD="1" IMAGE_INDEX_VALUE="2">
<ID>1</ID>
<PRODUCT_NAME>Item1</PRODUCT_NAME>
<UNIT_PRICE>45035</UNIT_PRICE>
</Products>
A generált XML az alkalmazás mappájának /resources alkönyvtárában tárolódik három képállománnyal egyetemben, melyek a TreeView-ban megadott ImageList objektum elemei lesznek.
A DataSet objektum adatai megtekinthetők az alkalmazás Form-ján elhelyezett TabControl kontrol ’Generált XML forrása’ feliratú füle alatt elhelyezett DataGrid kontrolban.
Az attribútum-oszlopok ’1’, illetve ’2’ értéket kapnak, melyek a megjelenítendő képállomány sorszámainak felelnek meg.
A TabControl másik – ’XML keresése’ feliratú – füle alatt megadható a megjelenítendő XML állomány neve teljes elérési útvonallal. Az állomány keresésében egy OpenFileDialog komponens nyújt segítséget, mely csak XML állományokat jelenít meg, szűrve az állományokat.
A minden szempontból megfelelő XML állományokat a BuildTreeView tagmetódussal dolgozzuk fel, és jelenítjük meg a TreeView-ban.
A programban két-, illetve háromszintű XML állományokat tudunk feldolgozni, melyek megfelelnek a szabványos, táblázatosan is felírható állományok előírásainak. A kétszintű XML formája:
<?xml version="1.0" encoding="utf-8" ?>
<Main>
<Sub1>...</Sub1>
<Sub1>...</Sub2>
...
</Main>
Háromszintű XML például a DataSet objektum WriteXml metódusával generált állomány, melynek gyökértagja a <NewDataSet> nevet viseli, és amely mintegy keretbe foglalja az információt:
<?xml version="1.0" standalone="yes"?>
<NewDataSet>
<Products IMAGE_INDEX_HEAD="1" IMAGE_INDEX_VALUE="2">
<ID>1</ID>
<PRODUCT_NAME>Item1</PRODUCT_NAME>
<UNIT_PRICE>45035</UNIT_PRICE>
</Products>
...
</NewDataSet>
A BuildTreeView metódusban sorra végigmegyünk az állomány elemein, kezdve azzal, hogy betöltjük a felépítendő fa forrás XML-jét:
private int BuildTreeView()
{
int res = 0;
try
{
XmlDocument doc = new XmlDocument();
doc.Load(pathText.Text);
Létrehozunk egy-egy TreeNode objektumot a felfűzendő elemeknek, valamint egy-egy listát az XML elemek beolvasásához:
TreeNode rowHead = null;
TreeNode colHead = null;
TreeNode colBody = null;
XmlNodeList colList;
XmlNodeList rowList;
XmlNodeList rootList;
Beolvassuk a gyökérelem nevét:
rootList = doc.GetElementsByTagName(doc.DocumentElement.Name);
...
Gyökérelemünk csak egy van, a <NewDataSet> elem, melynek sorokat reprezentáló <Products> elemeit betöltjük egy lista objektumba, hogy aztán elemeit listázhassuk:
for( int m=0;m<rootList.Count;m++)
{
XmlElement mainElement = (XmlElement)rootList.Item(m);
rowList = mainElement.ChildNodes ;
Kezdünk végigmenni a Products-lista elemein, melyek a három oszlop elemei:
for( int i =0;i<rowList.Count;i++)
{
XmlElement rowElement = (XmlElement)rowList.Item(i);
A két attribútumként megjelenő oszlopérték olvasása érdekében – melyek a <Products> elemekben tárolódnak -, létrehozunk egy attribútum listát, melynek elemeire sorszámmal hivatkozhatunk, ha a kollekció nem üres:
XmlAttributeCollection attrColl = rowElement.Attributes;
if (attrColl.Count == 2)
{
if (attrColl[0].Name == "IMAGE_INDEX_HEAD" && attrColl[1].Name == "IMAGE_INDEX_VALUE")
{
index_head = Convert.ToInt32(attrColl[0].Value);
index_value = Convert.ToInt32(attrColl[1].Value);
}
}
A <Products> elemek gyermek elemein is végigmegyünk egy ciklussal, azonban az egyes gyermek elemek eltérőek lehetnek attól függően, hogy háromszintű XML-t dolgozunk fel, mint a generált állományunk, vagy csak egy kétszintűt:
rowHead = new TreeNode(rowElement.Name);
colList = rowElement.ChildNodes ;
for( int j =0;j<colList.Count;j++)
{
A generált XML-ünk második – jelen esetben <Products> nevet viselő – szintje tartalmaz gyermek elemeket, míg a kétszintű XML-ek második szintje csak egy belső szöveget. Előbbi esetben a gyermek elemek XmlElement objektumok, melyeknek neve, és szövege is van, míg utóbbi esetben a lista elemek XmlText objektumok, csak szöveggel. Egy feltétellel így meg kell vizsgálnunk, hogy milyen típusról van szó:
if (colList.Item(j).GetType().Name == "XmlElement")
{
Az egyes elemeket paraméterezzük, majd felfűzzük TreeNode objektumként egy TreeView csomópontra:
XmlElement colElement = (XmlElement)colList.Item(j);
colHead = new TreeNode(colElement.Name);
...
colBody = new TreeNode(colElement.InnerText);
...
colHead.Nodes.Add(colBody);
rowHead.Nodes.Add(colHead);
}
Ugyanígy a másik típus esetén is:
else if (colList.Item(j).GetType().Name == "XmlText")
{
XmlText colText = (XmlText)colList.Item(j);
colBody = new TreeNode(colText.InnerText);
...
rowHead.Nodes.Add(colBody);
}
}
Végül egy sor-csomópontot felfűzünk, a művelet végén pedig kibontva jelenítjük meg az elemeket:
xmlTree.Nodes[0].Nodes.Add(rowHead);
}
}
xmlTree.Nodes[0].Expand();
}
...
}
A metódus meghívása után a sor-elemeknek megfelelő tagok attribútum listájából kiolvasott értékeknek megfelelően jelennek meg a gyermek elemek, a megfelelő képállományokat tartalmazva csomópontjaikban. Attribútummal nem rendelkező állományok esetén a TreeView kontrol alapértelmezett képei jelennek meg, melyek a listában 0 sorszámmal szerepelnek.