#c# #asp.net #linq #repeater
#c# #asp.net #linq #repeater
Вопрос:
Я пытаюсь вывести список элементов иерархической навигации из моей CMS следующим образом:
YEAR
- MONTH
- - ARTICLE 1
- - ARTICLE 2
Страница оформлена так, что если вы находитесь на странице year, вы увидите:
MONTH
- ARTICLE 1
- ARTICLE 2
Очевидно, что если вы находитесь на странице месяца, вы просто увидите ссылку на статьи
Я пытаюсь создать запрос LINQ для обработки логики, а затем встроить его в DataTable, который будет обрабатываться Repeater. Я действительно изо всех сил пытаюсь понять логику, чтобы я мог построить это правильным образом. Логически LINQ оказался самым простым способом смоделировать это, хотя сейчас у меня возникли другие мысли. Это код, который я придумал, чтобы получить годы и необходимые данные на данный момент.
var linqYears = from year in contextItem.Children
select new
{
Name = year.Fields["page title"],
URI = Sitecore.Links.LinkManager.GetItemUrl(year)
};
Что мне нужно сейчас, так это получить все месяцы за выбранный год, а затем все статьи и встроить их в repeater; Я предполагаю, что самый простой способ сделать это — с помощью DataTable / DataSet?
Буду признателен за любую помощь.
РЕДАКТИРОВАТЬ: Чтобы прояснить мою позицию:
Элемент contextItem — это страница, на которой я сейчас нахожусь. Если я нахожусь на корневой странице, а страница года находится подо мной, тогда contextItem.Дочерние элементы вернут всех дочерних элементов под ним. Например, учитывая эту навигацию, если я нахожусь в ROOT:
ROOT
- YEAR
- - MONTH
- - - ARTICLE 1
- - - ARTICLE 2
Затем contextItem.Дочерними элементами будет коллекция, состоящая исключительно из YEAR
Комментарии:
1. Не могли бы вы предоставить общую структуру классов
Year
,Month
иcontextItem.Children
?2. Я добавил еще немного, чтобы прояснить, что я делаю с кодом. Достаточно ли этого?
3. Вы имеете в виду, что хотите, чтобы LINQ-query динамически обрабатывал текущую позицию независимо от уровня в иерархии?
4. @Emil Badh: Да. Ваш код работает в корневом каталоге, и я верю, что он сработает, если я использую его в любом из подпунктов, но динамическое позиционирование определенно было бы полезно в коде, чтобы я не проверял элементы, которые, как я знаю, не будут существовать.
5. Я расширил свой ответ. Посмотрите, то ли это, что вам нужно и / или понятно.
Ответ №1:
Я не знаком с вашей структурой, но я предполагаю, что здесь это year
тот же тип, что и contextItem
. Если да, то это сработало бы:
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)
}
}
};
Я не уверен насчет repeater, но рассматривали ли вы возможность использования ListView вместо этого? Если я не ошибаюсь, вы можете привязать это непосредственно к вашим анонимным типам. Это работает, только если вы, конечно, делаете этот выбор встроенным. В противном случае я бы рекомендовал создать класс, содержащий Name, URI и дочерние элементы, и заменить Months
и Articles
соответственно в приведенном выше коде на Children
.
Надеюсь, это поможет.
РЕДАКТИРОВАТЬ: Чтобы заставить это решение работать независимо от вашего текущего положения в иерархии, вы могли бы сделать что-то вроде этого:
Сначала создайте класс для своих страниц.
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...
}
Тогда вам нужны методы, подобные этому:
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
};
}
Комментарии:
1. Будь ты проклят, Эмиль, ты меня опередил 🙂
2. Оценка! 😛 Я сам часто это понимаю. Это сообщество чертовски полезно. 🙂
3. Спасибо за помощь; Я оставил для вас комментарий к комментариям к вопросу.