使用 LINQ 为 Repeater 构建分层导航

发布于 2024-10-30 09:16:30 字数 1008 浏览 1 评论 0原文

我正在尝试从我的 CMS 输出项目的分层导航列表,如下所示:

YEAR
- MONTH
- - ARTICLE 1
- - ARTICLE 2

该页面已模板化,因此如果您在年份页面上,您将看到:

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)
                };

我现在需要的是获取所选年份的所有月份,然后获取所有文章并将它们构建为中继器;我认为最简单的方法是通过数据表/数据集?

任何帮助将不胜感激。

编辑:澄清我的立场:

项目 contextItem 是我当前所在的页面。如果我位于根页面并且年份页面位于我下方,则 contextItem.Children 将返回其下方的所有子级。例如,如果我在 ROOT 上,给定此导航:

ROOT
- YEAR
- - MONTH
- - - ARTICLE 1
- - - ARTICLE 2

那么 contextItem.Children 将是仅由 YEAR 组成的集合

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 contextItem.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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

叫嚣ゝ 2024-11-06 09:16:30

我不熟悉您的结构,但我假设 yearcontextItem 的类型相同。如果是这样,这会起作用:

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)
                                            }
                             }
                };

我不确定中继器,但您是否考虑过使用 ListView 来代替?除非我弄错了,否则您可以将其直接绑定到您的匿名类型。当然,只有当您内联进行此选择时,这才有效。否则,我建议创建一个包含 Name、URI 和 Children 的类,并分别用 Children 替换上述代码中的 MonthsArticles

希望有帮助。

编辑:
为了使该解决方案正常工作,无论您当前在层次结构中的位置如何,您都可以执行以下操作:

首先为您的页面创建一个类。

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
           };
}

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
           };
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文