Added DynamicNodeWalker and implementation on DynamicNode and DynamicNodeList

DynamicNodeWalker is our secret weapon in the fight against the Rebel XSLT Alliance
Navigate nodes by calling Up(), Down(), Next() and Previous() on them
Next(1) will jump two items along within the current list, whereas Next() will walk by one within the list
Previous(1) will move two items backwards within the current list
Up() is a special wrapper around .Parent which has an overload .Up(int) to replace @Model.Parent.Parent.Parent... [.Up(2)]
Down() will take you to the first Child item and is equivilent to .Children.First(), use .Down(1) to replace .Children.First().Children
If one of the NodeWalker functions fails to find a node at the requested position, it will return null
This commit is contained in:
agrath@gmail.com
2011-02-24 17:19:50 -13:00
parent 603a12c5a0
commit 71c5e35443
4 changed files with 161 additions and 24 deletions

View File

@@ -19,8 +19,9 @@ namespace umbraco.MacroEngines
{
public class DynamicNode : DynamicObject
{
internal DynamicNodeList ownerList;
private readonly INode n;
internal readonly INode n;
public DynamicNode(INode n)
{
if (n != null)
@@ -53,6 +54,39 @@ namespace umbraco.MacroEngines
//Empty constructor for a special case with Generic Methods
}
public DynamicNode Up()
{
return DynamicNodeWalker.Up(this);
}
public DynamicNode Up(int number)
{
return DynamicNodeWalker.Up(this, number);
}
public DynamicNode Down()
{
return DynamicNodeWalker.Down(this);
}
public DynamicNode Down(int number)
{
return DynamicNodeWalker.Down(this, number);
}
public DynamicNode Next()
{
return DynamicNodeWalker.Next(this);
}
public DynamicNode Next(int number)
{
return DynamicNodeWalker.Next(this, number);
}
public DynamicNode Previous()
{
return DynamicNodeWalker.Previous(this);
}
public DynamicNode Previous(int number)
{
return DynamicNodeWalker.Previous(this, number);
}
public DynamicNodeList GetChildrenAsList
{
get

View File

@@ -22,11 +22,15 @@ namespace umbraco.MacroEngines
}
public DynamicNodeList(IEnumerable<DynamicNode> items)
{
Items = items.ToList();
List<DynamicNode> list = items.ToList();
list.ForEach(node => node.ownerList = this);
Items = list;
}
public DynamicNodeList(IEnumerable<INode> items)
{
Items = items.Select(x => new DynamicNode(x)).ToList();
List<DynamicNode> list = items.Select(x => new DynamicNode(x)).ToList();
list.ForEach(node => node.ownerList = this);
Items = list;
}
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)

View File

@@ -0,0 +1,98 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using umbraco.interfaces;
namespace umbraco.MacroEngines
{
public static class DynamicNodeWalker
{
public static DynamicNode Up(this DynamicNode context)
{
return context.Up(0);
}
public static DynamicNode Up(this DynamicNode context, int number)
{
if (number == 0)
{
return context.Parent;
}
else
{
while ((context = context.Parent) != null && --number >= 0) ;
return context;
}
}
public static DynamicNode Down(this DynamicNode context)
{
return context.Down(0);
}
public static DynamicNode Down(this DynamicNode context, int number)
{
DynamicNodeList children = new DynamicNodeList(context.ChildrenAsList);
if (number == 0)
{
return children.Items.First();
}
else
{
DynamicNode working = context;
while (number-- >= 0)
{
working = children.Items.First();
children = new DynamicNodeList(working.ChildrenAsList);
}
return working;
}
}
public static DynamicNode Next(this DynamicNode context)
{
return context.Next(0);
}
public static DynamicNode Next(this DynamicNode context, int number)
{
if (context.ownerList != null)
{
List<DynamicNode> container = context.ownerList.Items.ToList();
int currentIndex = container.IndexOf(context);
if (currentIndex != -1)
{
return container.ElementAtOrDefault(currentIndex + (number + 1));
}
else
{
throw new IndexOutOfRangeException(string.Format("Node {0} belongs to a DynamicNodeList but could not retrieve the index for it's position in the list", context.Id));
}
}
else
{
throw new ArgumentNullException(string.Format("Node {0} has been orphaned and doesn't belong to a DynamicNodeList", context.Id));
}
}
public static DynamicNode Previous(this DynamicNode context)
{
return context.Previous(0);
}
public static DynamicNode Previous(this DynamicNode context, int number)
{
if (context.ownerList != null)
{
List<DynamicNode> container = context.ownerList.Items.ToList();
int currentIndex = container.IndexOf(context);
if (currentIndex != -1)
{
return container.ElementAtOrDefault(currentIndex + (number - 1));
}
else
{
throw new IndexOutOfRangeException(string.Format("Node {0} belongs to a DynamicNodeList but could not retrieve the index for it's position in the list", context.Id));
}
}
else
{
throw new ArgumentNullException(string.Format("Node {0} has been orphaned and doesn't belong to a DynamicNodeList", context.Id));
}
}
}
}

View File

@@ -63,29 +63,30 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="BaseContext.cs" />
<Compile Include="DynamicNodeList.cs" />
<Compile Include="DynamicQueryable.cs" />
<Compile Include="DynamicXml.cs" />
<Compile Include="ExtensionMethods.cs" />
<Compile Include="RazorUmbracoFactory.cs" />
<Compile Include="RazorUmbracoHost.cs" />
<Compile Include="UmbracoCultureDictionary.cs" />
<Compile Include="RazorCore\BaseContext.cs" />
<Compile Include="RazorDynamicNode\DynamicNodeList.cs" />
<Compile Include="RazorDynamicNode\DynamicNodeWalker.cs" />
<Compile Include="RazorDynamicNode\DynamicQueryable.cs" />
<Compile Include="RazorDynamicNode\DynamicXml.cs" />
<Compile Include="RazorDynamicNode\ExtensionMethods.cs" />
<Compile Include="RazorCore\RazorUmbracoFactory.cs" />
<Compile Include="RazorCore\RazorUmbracoHost.cs" />
<Compile Include="RazorCore\UmbracoCultureDictionary.cs" />
<Compile Include="DLRScriptingEngine.cs" />
<Compile Include="DynamicDictionary.cs" />
<Compile Include="DynamicNodeListExtensionMethods.cs" />
<Compile Include="DynamicNodeListOrdering.cs" />
<Compile Include="DynamicQueryableBinders.cs" />
<Compile Include="DynamicMedia.cs" />
<Compile Include="DynamicNode.cs" />
<Compile Include="DynamicNodeContext.cs" />
<Compile Include="ICultureDictionary.cs" />
<Compile Include="IMacroContext.cs" />
<Compile Include="IParameterDictionary.cs" />
<Compile Include="UmbracoParameterDictionary.cs" />
<Compile Include="RazorDynamicNode\DynamicDictionary.cs" />
<Compile Include="RazorDynamicNode\DynamicNodeListExtensionMethods.cs" />
<Compile Include="RazorDynamicNode\DynamicNodeListOrdering.cs" />
<Compile Include="RazorDynamicNode\DynamicQueryableBinders.cs" />
<Compile Include="RazorDynamicNode\DynamicMedia.cs" />
<Compile Include="RazorDynamicNode\DynamicNode.cs" />
<Compile Include="RazorDynamicNode\DynamicNodeContext.cs" />
<Compile Include="RazorCore\ICultureDictionary.cs" />
<Compile Include="RazorCore\IMacroContext.cs" />
<Compile Include="RazorCore\IParameterDictionary.cs" />
<Compile Include="RazorCore\UmbracoParameterDictionary.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RazorBuildProvider.cs" />
<Compile Include="RazorMacroEngine.cs" />
<Compile Include="RazorCore\RazorBuildProvider.cs" />
<Compile Include="RazorCore\RazorMacroEngine.cs" />
<Compile Include="Scripting\MacroScript.cs" />
<Compile Include="Scripting\ScriptEngine.cs" />
</ItemGroup>