ASPX templates
Version 6.x > ASPX templates > Get TreeNode from TreeNodeCollection View modes: 
User avatar
Member
Member
robert-tailor.co - 9/10/2012 5:47:34 PM
   
Get TreeNode from TreeNodeCollection
Hi,

What's the deal with TreeNodeCollection? How can I select an individual TreeNode from a TreeNodeCollection?

Let's say I have the following query which returns a TreeNodeCollection:

TreeNodeCollection myChildren = (from c in rangeNode.Children
orderby c.NodeLevel ascending
select c);


Now let's try and get a single element from myChildren:

myChildren[0]


Fails with "Cannot apply indexing with [] to an expression of type 'System.Linq.IOrderedQueryable<CMS.TreeEngine.TreeNode>'"

Now let's try:

myChildren.FirstOrDefault()


Fails with "Unable to cast object of type 'CMS.TreeEngine.TreeNodeCollection' to type 'CMS.TreeEngine.TreeNode'."

OK, let's try:

firstChild.Take(1)


Works!

Is there any reason why FirstOrDefault() doesn't work with TreeNodeCollection?

User avatar
Kentico Customer Success
Kentico Customer Success
kentico_martind2 - 9/11/2012 4:39:54 AM
   
RE:Get TreeNode from TreeNodeCollection
Hi,

In the Kentico CMS API Documentation you can look for TreeNodeCollection Class where you can find the methods usable with this class... there is method called "GetItem(Int32)" - Gets the item on the specified index.

Probably you will need to cast it to the type (TreeNode) after you have object (item) selected.

You can not cast the whole collection to type 'CMS.TreeEngine.TreeNode' but just one single object (node) of the collection.

I don't know what exactly is your goal but you can also use TreeProvider and SelectSingleNode method, see examples in the DevGuide: Managing documents

User avatar
Member
Member
robert-tailor.co - 9/11/2012 6:51:13 PM
   
RE:Get TreeNode from TreeNodeCollection
kentico_martind2 wrote: In the Kentico CMS API Documentation you can look for TreeNodeCollection Class where you can find the methods usable with this class... there is method called "GetItem(Int32)" - Gets the item on the specified index.

Although this method is listed in the API Documentation, it does not exist in the API itself.

Look in the CMS.TreeEngiine.TreeNodeCollection class (the actual class in Visual Studio, not the API Documentation) - there is no GetItem() method.

kentico_martind2 wrote: I don't know what exactly is your goal but you can also use TreeProvider and SelectSingleNode method, see examples in the DevGuide: Managing documents


I want to select the first child node under the current node, but I do not know (or care) what node ID is.

So, this should work:

CMS.TreeEngine.TreeNode child = CMSContext.CurrentDocument.Children.OrderBy(c => c.NodeLevel).FirstOrDefault();


But it doesn't. I get the following error:

"Unable to cast object of type 'CMS.TreeEngine.TreeNodeCollection' to type 'CMS.TreeEngine.TreeNode'."

FirstOrDefault() should return a single object class (TreeNode) of TreeNodeCollection, but it looks like it is returning TreeNodeCollection instead.

It looks like TreeNodeCollection does not properly implement generic collections, so standard LINQ comands will not work properly with it.

How can I perform the equivalent of the code above?

User avatar
Member
Member
robert-tailor.co - 9/11/2012 6:52:52 PM
   
RE:Get TreeNode from TreeNodeCollection
Interestingly, Visual Studio's Intellisense thinks that FirstOrDefault() *will* return a TreeNode class. But at runtime, it returns TreeNodeCollection.

This does not look right to me.

User avatar
Kentico Customer Success
Kentico Customer Success
kentico_martind2 - 9/12/2012 6:37:59 AM
   
RE:Get TreeNode from TreeNodeCollection
Hi Robert,

If you have really read the Kentico API Documentation, under GetItem() method is also the note:
(Inherited from ObjectCollection<(Of <(<'ObjectType>)>)>.)
... so this is the reason why you can't see this method in the TreeNodeCollection class because it is inherited.

Read carefully documentation of FirstOrDefault() Method where you can find:
In Visual Basic and C#, you can call this method as an instance method on any object of type IEnumerable<TSource>.
Of course, it won't work with CMSContext.CurrentDocument because as you can read (again) in the Kentico API Documentation, it "Returns the current document node" which isn't the object of type IEnumerable.

I'm sorry, but I was unable to reproduce this behaviour, Visual Studio's Intellisense doesn't offer me method FirstOrDefault() with the CMSContext.CurrentDocument class as the option.

Best regards,
Martin Danko

User avatar
Member
Member
robert-tailor.co - 9/12/2012 4:36:31 PM
   
RE:Get TreeNode from TreeNodeCollection
kentico_martind2 wrote: Read carefully documentation of FirstOrDefault() Method where you can find:
In Visual Basic and C#, you can call this method as an instance method on any object of type IEnumerable<TSource>.
Of course, it won't work with CMSContext.CurrentDocument because as you can read (again) in the Kentico API Documentation, it "Returns the current document node" which isn't the object of type IEnumerable.

Hi Martin,

I think you may have misread my post.

I'm not trying to select an item from CMSContext.CurrentDocument - as you say, it's a TreeNode object, not a TreeNodeCollection.

I am trying to select an item from CMSContext.CurrentDocument.Children (which is a TreeNodeCollection).

Try this exact line of code for yourself in a Page Template code-behind:

TreeNodeCollection myChildren = (from c in CMSContext.CurrentDocument.Children
orderby c.NodeLevel ascending
select c);
TreeNode firstChild = myChildren.FirstOrDefault();


You should be able to reproduce the behaviour I'm describing:

1. myChildren is a TreeNodeCollection of TreeNode objects. GetItem is *not* a member of this collection.
2. FirstOrDefault() should work on *any* collection of objects that implement IQueryable. But it doesn't work in this case.

Given that the above code doesn't work, and my *intention* is to get the first Node (regardless of NodeID) in my TreeNodeCollection, what code *should* I use to achieve this?

Thanks.

User avatar
Kentico Customer Success
Kentico Customer Success
kentico_martind2 - 9/13/2012 5:58:09 AM
   
RE:Get TreeNode from TreeNodeCollection
Hi Robert,

Ok, I'm sorry for misunderstanding.

I've been testing your code and get it working after a few issues solved (and a little bit of googling).

Try the following code, I trust it would do what you exactly want:
using System.Linq; // don't forget
using System.Collections.Generic;

CMS.TreeEngine.TreeNodeCollection myChildren = CMSContext.CurrentDocument.Children;
IEnumerable<CMS.TreeEngine.TreeNode> test = myChildren.AsEnumerable<TreeNode>();
CMS.TreeEngine.TreeNode myNode = test.FirstOrDefault<TreeNode>();

Best regards,
Martin Danko