den 6 november 2009
av
Fredrik Sewen
För ett tag sen dök det upp en fråga på our.umbraco.org om hur
man får tag i alla descendant nodes av en viss dokumenttyp med en
.NET-funktion. Se hela
frågan här.
Frågan besvarades förvisso, men jag är inte jätteförtjust i att
jobba med XPaths i .NET så jag tänkte föreslå en rekursiv approach
istället.
Idén med en rekursiv funktion är att man vandrar uppför grenar i
trädet, tills man når ett löv. Då returnerar man funktionen och
hamnar en gren tillbaka och ser om det finns fler grenar/löv på den
grenen. T.ex;
Vi har strukturen
-2009
--8
---19
--10
---16
---22
--11
---6
I det här fallet får vår rekursiva funktion börja på 2009. När
vi frågar efter Children till 2009 returneras 8,10,11.
Vi vandrar då uppför 8 och frågar efter Children och får 19. Vi
märker då att 19 är ett löv, och lägger därför till den till vår
lista.
Därefter returnerar vi och kommer tillbaka till 8. Eftersom 8
inte har några fler Children lägger vi även till 8 till vår lista,
och returnerar.
Vi är tillbaka till 2009 och går vidare längs nästa gren 10. 10
har två löv 16 och 22. Vi lägger till dessa och returnerar från
10.
På den vägen är det. Eller som Sluggo skulle förklara det:

Till programmeringen:
Vi börjar med att lägga till properties som vi vet att vi kommer
behöva. En för startnod och en för dokumenttyp.
TIPS! Du vet att ud kan skriva prop + tab + tab för att få en
automatisk generering av properties i Visual Studio.
private int rootNode = 0;
public int RootNode { get { return rootNode; } set { rootNode = value; } }
private string documentTypeAlias = "";
public string DocumentTypeAlias { get { return documentTypeAlias; } set { documentTypeAlias = value; } }
Sedan går vi in i Page_Load och deklarerar vår lista samt sätter
igång vår rekursiva funktion, där vi skickar in vår startnod, vår
lista och den dokumenttyp vil vill ha.
protected void Page_Load(object sender, EventArgs e) {
List nodeList = new List();
AddAllDescendants(new Node(rootNode), nodeList, documentTypeAlias);
}
Så är det dags att skapa magin, vår rekursiva funktion.
private void AddAllDescendants(Node CurrentNode, List<Node> NodeList, string DocumentTypeAlias) {
foreach (Node n in CurrentNode.Children) {
AddAllDescendants(n, NodeList, DocumentTypeAlias);
}
if (string.IsNullOrEmpty(DocumentTypeAlias) || CurrentNode.NodeTypeAlias == DocumentTypeAlias) {
NodeList.Add(CurrentNode);
}
}
Det första vi gör är att för alla children, kalla på vår
rekursiva funktion igen. Då vandrar vi uppför en gren. När vi gått
igenom hela foreach-loopen (eller om vi når ett löv som inte har
någon foreach) så lägger vi till vår nod i listan. Här gör vi en
check som kollar om Nodtypen är den vi söker (eller om dokumenttyp
är tom så lägger vi till alla noder). Därefter returnerar
funktionen och vandrar nedför trädet igen.
När vi är tillbaka i Page_Load har vi fyllt får nodeList med
alla noder av den typ vi vill ha. Härifrån är det fritt att göra
vad man vill med listan, tex sortera:
nodeList.Sort(delegate(Node n1, Node n2) {
return n1.Name.CompareTo(n2.Name);
});
Ladda ner hela lösningen här: DescendantNodes_NET.zip