【问题标题】:Render child items with their own layout in a carousel control在轮播控件中呈现具有自己布局的子项
【发布时间】:2013-07-24 13:16:34
【问题描述】:

这是我想要做的:

我有一个内容项“轮播演示者”。本质上,这将在轮播中显示其子项。我希望灵活地拥有任意数量的子项目。我还希望能够灵活地指定每个子项目的呈现方式——它们可能相同或不同。我正在使用 Sitecore 6.5。

轮播是 jcarousel。我需要生成这样的标记(来自项目“Carousel Presenter”):

<div class="jcarousel">
    <ul>
        <li> ... MARKUP FROM ITEM 1 ... </li>
        <li> ... MARKUP FROM ITEM 2 ... </li>
        ... and so on
    </ul>
</div>

这是我尝试过的:

  • 创建子布局“carousel presenter.ascx”,标记:

    代码隐藏:

      protected void Page_Load(object sender, EventArgs e)
        {
            // Get all children and render them inside the <ul>
            var kids = Sitecore.Context.Item.GetChildren();
            foreach (Item snippet in kids)
            {
                // RENDER THE ITEMS HERE INTO THE PLACEHOLDER...
                // Get the first rendering from item's presentation definition
                RenderingReference rendering = snippet.Visualization.GetRenderings(Sitecore.Context.Device, false).FirstOrDefault();
                // We assume that its a Sublayout, but you can also check for xslt and create an XslFile() object
                Sublayout sublayout = new Sublayout();
                sublayout.DataSource = snippet.Paths.FullPath; // creates a reference to the snippet item, so you can pull data from that later on
                sublayout.Path = rendering.RenderingItem.InnerItem["Path"];
                sublayout.Cacheable = rendering.RenderingItem.Caching.Cacheable;
                // Copy cache settings
                if (rendering.RenderingItem.Caching.Cacheable)
                {
                    sublayout.VaryByData = rendering.RenderingItem.Caching.VaryByData;
                    sublayout.VaryByDevice = rendering.RenderingItem.Caching.VaryByDevice;
                    sublayout.VaryByLogin = rendering.RenderingItem.Caching.VaryByLogin;
                    sublayout.VaryByParm = rendering.RenderingItem.Caching.VaryByParm;
                    sublayout.VaryByQueryString = rendering.RenderingItem.Caching.VaryByQueryString;
                    sublayout.VaryByUser = rendering.RenderingItem.Caching.VaryByUser;
                }
                // Now render the sublayout to the placeholder
                carouselItemsPh.Controls.Add(sublayout);
            }
        }
    

    请注意,我从这里窃取了大部分代码:Temporarily change a Sitecore item's layout

    • 在内容树中创建了子项,位于内容项“Carousel Presenter”下方,即“Carousel Items”,并为每个子项分配了一个子布局控件(通过配置/布局中的标准值)。

    所有内容都已发布。

    当我点击测试页面时,会为每个子项(“轮播项”)生成标记,并且轮播可以工作,但看起来数据源没有正确分配 - 所有子项的数据源/上下文是父项,尽管在我创建子控件时明确设置了数据源。我该如何解决这个问题?

    有没有更好的方法来实现我在 Sitecore 6.5 中实现的目标?

    谢谢

    【问题讨论】:

      标签: asp.net content-management-system sitecore sitecore6


      【解决方案1】:

      您的子项目的用户控件/子布局需要以编程方式读取数据源。对于这项工作,我总是有自己的“基础”子布局类来处理用户控件的数据源问题。在我的基类中,如果尚未设置数据源,我默认使用 Sitecore.Context.Item。代码如下:

      public class SublayoutBase : UserControl
      {
          private Item _dataSource;
      
          public Item DataSource
          {
              get
              {
                  if (_dataSource == null)
                  {
                      if (Parent is Sublayout)
                      {
                          _dataSource =
                              Sitecore.Context.Database.GetItem(((Sublayout)Parent).DataSource);
                      }
                      if (_dataSource == null)
                      {
                          _dataSource = Sitecore.Context.Item;
                      }
                  }
                  return _dataSource;
              }
          }
      
          protected override void OnLoad(EventArgs e)
          {
              foreach (Control c in Controls)
              {
                  SetFieldRenderers(DataSource, c);
              }
              base.OnLoad(e);
          }
      
          private void SetFieldRenderers(Item item, Control control)
          {
              if (item != null)
              {
                  var ctrl = control as Sitecore.Web.UI.WebControl;
                  if (ctrl != null && !string.IsNullOrEmpty(ctrl.DataSource))
                  {
                      //don't set the source item if the DataSource has already been set. 
                      return;
                  }
                  if (control is FieldRenderer)
                  {
                      var fr = (FieldRenderer)control;
                      fr.Item = item;
                  }
                  else if (control is Image)
                  {
                      var img = (Image)control;
                      img.Item = item;
                  }
                  else if (control is Link)
                  {
                      var link = (Link)control;
                      link.Item = item;
                  }
                  else if (control is Text)
                  {
                      var text = (Text)control;
                      text.Item = item;
                  }
                  else
                  {
                      foreach (Control childControl in control.Controls)
                      {
                          SetFieldRenderers(item, childControl);
                      }
                  }
              }
          }
      }
      

      【讨论】:

      • 那是我所缺少的拼图——谢谢
      【解决方案2】:

      我倾向于为这样的事情创建一个Repeater

      你可以这样做:

      <div class="jcarousel">
          <asp:Repeater id="repeater" runat="server">
              <HeaderTemplate>
                  <ul>
              </HeaderTemplate>
              <ItemTemplate>
                  <li>
                      ..markup from item such as:
                      <sc:FieldRenderer FieldName="Title" runat="server" id="titlefield" Item="<%# Container.DataItem %>" />
                  </li>
              </ItemTemplate>
              <FooterTemplate>
                  </ul>
              </FooterTemplate>
          </asp:Repeater>
      </div>
      

      然后在 CodeBehind 中你需要做的就是:

      protected void Page_Load(object sender, EventArgs e)
      {
          repeater.DataSource = Sitecore.Context.Item.GetChildren(); // Could also make a LINQ statement where you make sure Children are of specific template if required
          repeater.DataBind();
      }
      

      当然,这取决于你的子项目SubLayouts 是否可以使用这样的东西

      【讨论】:

      • 谢谢,但我故意不使用中继器,因为我不想在我的父控件中为孩子们添加标记。根据我的问题 - “我还希望能够灵活地指定每个子项目的呈现方式”
      • 抱歉,我错过了那部分 :-)
      猜你喜欢
      • 2011-10-29
      • 1970-01-01
      • 2023-01-18
      • 2013-02-04
      • 2021-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多