3

我有一个页面模板,它在页面底部的 div 中输出三个组件演示文稿。所有这三个组件演示文稿都使用相同的架构和 Dreamweaver 组件模板。

我想根据它们是该 div 中的第一个组件还是最后一个组件来稍微不同地设置这些组件表示的样式 - 基本上我想为每个组件表示添加“第一个”和“最后一个”CSS 类。

我正在尝试在模板构建块中为组件演示动态设置“参数”。以下是我到目前为止所得到的(不起作用,只是为了让您了解我正在尝试做的事情):

public override void Transform(Engine engine, Package package)
{
    var page = GetPage();
    var wantComponents =
        from c in page.ComponentPresentations
        where c.ComponentTemplate.Title == "Content highlight"
        select c;
    if (wantComponents.Count() > 0)
    {
        // pseudocode - won't compile!
        wantComponents.First().ComponentTemplate.Parameters["myCssClass"] = "first";
        wantComponents.Last().ComponentTemplate.Parameters["myCssClass"] = "last";
    }
    ...

在我的 Dreamweaver 模板中(同样,不起作用,只是为了让您了解我正在尝试做什么):

<div class="block @@Parameters.myCssClass@@">
    ...
</div>

如何将“第一个”CSS 类动态添加到页面上的第一个组件表示中,并将“最后一个”CSS 类添加到页面上的最后一个组件表示中?

4

2 回答 2

6

乔治这个问题一点也不坏。

如果您将 div 从组件模板中取出并将它们放入页面模板中,那么您不需要将页面模板中的参数传递到组件模板中。然后将 CSS 类设置为第一个组件表示很容易:

<div class="<!-- TemplateBeginIf cond="TemplateRepeatIndex==0" -->myFirstCssClass<!-- TemplateEndIf -->"></div>

在最后一个 Component Presentation 上设置一个类更有趣,有几种方法可以实现:

  1. 自定义 Dreamweaver 函数,例如 TemplateRepeatCount()。然后你可以在你的页面模板中做这样的事情: <!-- TemplateBeginRepeat name="Components" --><div class="<!-- TemplateBeginIf cond="TemplateRepeatIndex==TemplateRepeatCount()-1" -->lastCssClass<!-- TemplateEndIf -->">@@RenderComponentPresentation()@@</div><!-- TemplateEndRepeat -->.
  2. 另一种方法是编写一个基本的 TBB,对组件表示进行计数并将总数放到包中,然后您可以将 TemplateRepeatIndex 与此数字进行比较。

上面的 #1 和 #2 在我的文章中都有描述:http ://www.tridiondeveloper.com/more-fun-with-dreamweaver-templates-templaterepeatcount

最后,这是一种更符合您所询问的具体方法,即组件模板在何处实际查找页面范围以确定它是否是列表中的最后一个组件表示。这不是我最喜欢的,因为使用 TemplateBuilder 调试并不容易(因为当您通过 CT 运行时,您没有 PT,因此此范围内不存在组件表示计数)。

public class IsLastCP : TemplateBase
{
    private string MY_SCHEMA = "My Component's Schema Title";

    public override void Transform(Engine engine, Package package)
    {
        this.Initialize(engine, package);

        //in the page template.
        Page page = this.GetPage();
        if (page == null)
        {
            //this TBB is being executed either in Template Builder or a dynamic component presentation.
            // so we just don't do anything.
        }
        else
        {
            IList<ComponentPresentation> cpList = page.ComponentPresentations;

            int cpCount = 0;
            int thisCPIndex = -1;

            Component thisComponent = this.GetComponent();

            foreach (ComponentPresentation cp in cpList)
            {
                Component comp = cp.Component;
                if (comp.Schema.Title == MY_SCHEMA)
                {
                    if (comp.Id.Equals(thisComponent.Id))
                        thisCPIndex = cpCount;
                    cpCount++;
                }
            }

            if (thisCPIndex == cpCount-1)
            {
                package.PushItem("IsLastCP", package.CreateStringItem(ContentType.Text, "true"));
            }
        }
    }

为此,您需要 Will 著名的 TemplateBase 类,您可以从 SDLTridionWorld 提供的“有用的构建块”扩展中获得该类。显然,您需要调整我提供给您的架构名称等的代码。

在组件模板中将此 TBB 放在 Dreamweaver TBB 之前,然后像这样使用它的输出: <!-- TemplateBeginRepeat name="IsLastCP" -->class="myLastCSSClass"<!-- TemplateEndRepeat -->

注意:您不需要在此处执行 TemplateBeginIf 并在 IsLastCP 上明确检查真/假。如果有问题的 CP 是最后一个,那么这个变量将出现在包中,并且 TemplateBeginRepeat 子句将进入。

于 2012-06-25T04:20:51.360 回答
0

你也可以使用上下文变量来做这种事情。您不能直接从 DWT 执行此操作,因此这可能意味着可能编写函数源,或者可能将 DWT 替换为写入输出的程序集 TBB。如果这种方法适合您的设计,您可以engine.PublishingContext.RenderContext.ContextVariables从页面模板中写入一个变量,指示组件渲染是否是第一个,然后让组件模板读取它以确定要生成的输出。

一般来说,想法是在页面模板中写入变量并在组件模板中读取它们。这应该足以让您避免将组件模板关注点移动到页面模板中,当然,管道数量可能会让您望而却步。对于更极端的情况,可以从组件模板获取值到页面模板,但是你有更多的管道,所以想要这样做可能是一种设计味道。

于 2012-11-20T19:20:52.493 回答