Diskuze: Dynamické naplnění treeView
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.

Člen

Zobrazeno 11 zpráv z 11.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
Nějak nechápu co na tom konkrétně neumíš. Plus by bylo vhodné říct v jaké technologii to děláš.
Ahoj, programuju v C#. Mám následující tabulku.
- id - parentID - nazev
- 1 - 0 - a
- 2 - 1 - b
- 3 - 1 - c
- 4 - 3 - d
- 5 - 4 - e
z toho je jasné kdo je rodič a kdo je potomek. Jednoduchým cyklem si projdu tabulku a přidám nody.
IEnumerable<Lokace> lok = db.Lokace.ToArray();
foreach (Lokace lk in lok)
{
TreeNode node = new TreeNode();
node.Text = lk.nazev.ToString();
node.Value = lk.id.ToString();
if (lk.ParrentID != 0)
{
TreeNode tn = TreeView1.FindNode(Convert.ToString(lk.ParrentID));
tn.ChildNodes.Add(node);
}
else
{
TreeView1.Nodes.Add(node);
}
V tomto případě to ale vyhodí chybu při 4 průchodu smyčky. Jde o to, že metoda FindNode hleda hodnotu ValuePath. Při prvním průchodu a vložení prvního záznamu je valuePath prvního(root) nodu 1, to znamená, že v nasledujícím průchodu mě findNode najde nadřazený prvek, vloží do proměné tn a já můžu přiřadit potomka. Jenže node s ID 2 a 3 už mají valuePath 1/2(1/3) Což značí kam patří. U čtvrtého nodu tedy FindNode("3") nenajde nic. Potřebuji přidat potomka do nodu s valuePath "1/3". Tím pádem vyhodí následující řádek chybu, protože je mimo index. ValuePath s hodnotou 3 totiž neexistuje. A v tom je kámen úrazu. Předem to nevím jaká bude valuePath. Takže jak z toho ven? Napadlo mě udělat jeden vložený cyklus, který by prošel všechny nody a pak hledat v nalezených řetezcích hodnotu 3, ale to není dost dobře použitelný. Takže jak mám najít a přidat potomka k potomkovi? Ideální by bylo, když by jsem mohl hledat podle value, protože v ní mám jedinečný ID a měl bych tak jistotu, že dám prvek tam kam patří.
Snad jsem to popsal srozumitelně.
Napis si vlastni rekurzivni vyhledavani pro TreeNodeCollection.
Ahoj, to že je to C# mi došlo, ale šlo mi spíše o to jestli WF nebo WPF.
Ze tvého příkladu mi vyšlo něco takového (viz. obrázek dole). Nějak jsem nepřišel na to, proč by ti to někde něco nemělo najít. Každopádně jestli nemáš přesně zadanou db tabulku, tak to raději udělej skrz jednoduchou třídu:
class Location
{
public int Id { get; set; }
public Location Parent { get; set; }
public IList<Location> SubLocations { get; set; }
public string Name { get; set; }
public Location(int id, string name)
{
Id = id;
Name = name;
SubLocations = new List<Location>();
}
public void AddSubLocation(Location loc)
{
SubLocations.Add(loc);
loc.Parent = this;
}
}
Trošku jsem ti ale upravil vstupní data, tak kdyžtak upřesni jak přesně to s nimi je.
Pak teda podle tebe vstupní data vypadají takto:
Location a = new Location(1, "a");
Location b = new Location(2, "b");
Location c = new Location(3, "c");
Location d = new Location(4, "d");
Location e = new Location(5, "e");
a.AddSubLocation(b);
a.AddSubLocation(c);
c.AddSubLocation(d);
d.AddSubLocation(e);
var locactions = new List<Location> { a }; // to jen, že hlavních lokací tam máš asi víc, už podle příkladu.
No a nacpat to do TreeView už je jen rekurze..
private void FillTreeView(TreeView treeView, IEnumerable<Location> locations)
{
foreach (Location loc in locations)
treeView.Items.Add(CreateNode(loc));
}
private TreeViewItem CreateNode(Location location)
{
TreeViewItem actual = new TreeViewItem() { Header = location.Name };
foreach (Location subLocation in location.SubLocations)
actual.Items.Add(CreateNode(subLocation));
return actual;
}
Kdyžtak upřesni jak to máš s těmi daty, to zpětné hledání rodiče mi
přijde zbytečné
Btw, je to psáno ve WPF, takže na WF si tam musíš upravit pár věci (Items -> Nodes, TreeViewItem -> TreeNode, ...).
Ok, dík, mrknu na to a dám vědět, Jinak to píšu ve WF.
Koukal jsem na to a ten kód chápu. Ale není mě jasná jedna věc. Jak vytvořím programově za běhu objekty a,b,c,d,e a následně je programově přidám k rodičům? Nemůžu je psát deklarativně, potřebuji je napsat programově. Protože chci kód použít na několik druhů stromů, které se často mění. Proto jsem to řešil postupně načtením jednoho záznamu a vyhledání rodiče ke kterému patří a přidal.
Tak jsem to nakonec vyřešil rekurzivní metodou, která mě vrátí celou cestu k rodiči.
protected string GetValuePath(IEnumerable<Lokace> lokace, int id)
{
string valuePath = "";
string valuePathBack = "";
Lokace lok = (from lk in lokace
where lk.id == id
select lk).Single();
valuePath = Convert.ToString(lok.id);
int parent = Convert.ToInt32(lok.ParrentID);
if (parent != 0)
{
valuePathBack = GetValuePath(lokace, parent) + "/" + valuePath;
}
else
{
return valuePath;
}
return valuePathBack;
}
Následně ji válím při průchodu tabulkou s celým stromem
protected void Button1_Click(object sender, EventArgs e)
{
IEnumerable<Lokace> lok = db.Lokace.ToArray();
foreach (Lokace lk in lok)
{
TreeNode node = new TreeNode();
node.Text = lk.nazev.ToString();
node.Value = lk.id.ToString();
if (lk.ParrentID == 0)
TreeView1.Nodes.Add(node);
else
{
TreeNode tn = TreeView1.FindNode(GetValuePath(lok, Convert.ToInt32(lk.ParrentID)));
tn.ChildNodes.Add(node);
}
}
}
Nevím jestli je to v správný postup, ale dá se to aplikovat na jakýkoliv strom.
Proč není signatura té metody taková?
protected string GetValuePath(Lokace lokace)
Foreachuješ všechny lokace a pak je znova hledáš uvnitř té metody.
Hmm dost dobře nechápu jak to myslíš. Teda chápu tu signaturu, ale jak načtu ty jeho rodiče, když zavolám tu metodu jen s jediným objektem? Budu vědět, že má nějakého předka, ale když ho zavolám znovu, nemám mu přece co předat.
Zobrazeno 11 zpráv z 11.