I am trying to output a hierarchical navigation list of items from my CMS as follows:
YEAR
- MONTH
- - ARTICLE 1
- - ARTICLE 2
The page is templated so that if you are on the year page you will see:
MONTH
- ARTICLE 1
- ARTICLE 2
Obviously, if you're on the month page you'll just see a link to the articles
I am trying to build a LINQ query to handle the logic, and to then build it within a DataTable to be handled by a Repeater. I am really struggling to get the logic sound so that I can build this in the correct way. Logically, LINQ appeared to be the easiest way to model this, although I am now having second thoughts. This is the code I've come up with to get the years and the necessary data so far.
var linqYears = from year in cont开发者_如何学JAVAextItem.Children
select new
{
Name = year.Fields["page title"],
URI = Sitecore.Links.LinkManager.GetItemUrl(year)
};
What I need now is to get all months for the selected year, and then all the articles and build them into a repeater; I assume the easiest way to do this is through a DataTable/DataSet?
Any help would be greatly appreciated.
EDIT: To clarify my position:
The item contextItem is the page I am currently on. If I am on the root page and the year page is below me then contextItem.Children will return all children underneath it. For example, given this navigation if I am on ROOT:
ROOT
- YEAR
- - MONTH
- - - ARTICLE 1
- - - ARTICLE 2
Then contextItem.Children will be a collection consisting solely of YEAR
I'm not familiar with your structure but I assume here that year
is the same type as contextItem
. If so, this would work:
var linqYears = from year in contextItem.Children
select new
{
Name = year.Fields["page title"],
URI = Sitecore.Links.LinkManager.GetItemUrl(year),
Months = from month in year.Children
select new
{
Name = month.Fields["page title"],
URI = Sitecore.Links.LinkManager.GetItemUrl(month),
Articles = from article in month.Children
select new
{
Name = article.Fields["page title"],
URI = Sitecore.Links.LinkManager.GetItemUrl(article)
}
}
};
I'm not sure about the repeater but have you considered using a ListView instead? Unless I'm misstaken you can bind that directly to your anonymous types. That only works if you do this selection inline of course. Otherwise I'd recommend creating a class that contains Name, URI and Children and replace Months
and Articles
respectively in the above code with Children
.
Hope that helps.
EDIT: To make this solution work regardless of your current position in the hierarchy, you could do something like this:
First a class for your pages.
public class PageNode
{
public string Name { get; set; }
public Uri URI { get; set; }
public List<PageNode> Children { get; set; } // This should be done with a private setter, but you get that...
}
Then you need methods similar to this:
public IEnumerable<PageNode> GetChildNodes(IEnumerable<ContextItem> children)
{
return from c in children
select new PageNode()
{
Name = c.Fields["page name"],
URI = Sitecore.Links.LinkManager.GetItemUrl(c),
Children = c.Children.Any() ? GetChildNodes(c.Children) : null
};
}
public PageNode LoadNode(ContextItem item)
{
return new PageNode()
{
Name = item.Fields["page name"],
URI = Sitecore.Links.LinkManager.GetItemUrl(item),
Children = item.Children.Any() ? GetChildNodes(item.Children) : null
};
}
精彩评论