场景是我有很多 FieldRenderer。这些应该从不同的地方输出数据,一些来自项目 X,另一些来自项目 Y。并且应该输出项目 Z 的属性。
假设我有公共财产ItemX
我想从中输出一个属性,以下任何一个都可以。但我没有得到他们中任何一个的输出:
<sc:FieldRenderer runat="server" FieldName="Logo" DataSource="<%# ItemX %>" />
<sc:FieldRenderer runat="server" FieldName="Logo" DataSource="<%= ItemX.Paths.FullPath %>" />
<sc:FieldRenderer runat="server" FieldName="Logo" Item="<%# ItemX %>" />
<sc:FieldRenderer runat="server" FieldName="Logo" Item-ID="<%# ItemX.ID %>" />
<sc:FieldRenderer runat="server" FieldName="Logo" Item-ID-Guid="<%# ItemX.ID.Guid %>" />
如果我添加一个IDMyFieldRenderer
对其进行下面的丑陋的部分,我得到正确的输出:
MyFieldRenderer.Item = ItemX;
一定有更好的方法来做到这一点吗?我不确定这是 Sitecore 特定问题还是 WebForms 问题。
如果不使用隐藏代码,则无法将 FieldRenderer 的数据源设置为服务器端对象。这是 WebForms 工作方式的结果。该问题描述于微软知识库文章 http://support.microsoft.com/kb/976112:
显示表达式相当于仅包含 Response.Write(...) 语句的嵌入代码块。这是显示单个字符串、int 变量或常量等信息的最简单方法。 [...]请记住,显示表达式不能在服务器控件的属性中使用。这是因为 .NET Framework 直接编译整个表达式,而不是将显示内容作为属性的值。
换句话说,.NET 想要编译 sc:FieldRenderer,因此无权访问 的运行时内容。您可以通过尝试显示以下内容以更简单的形式查看此问题:
<asp:TextBox runat="server" Text="<%= DateTime.Now.ToString() %>" />
这呈现在文本框内。简而言之,除了服务器控件属性中的静态字符串之外,您无法获得任何其他内容。
此问题有几种可能的解决方案:
在 Page_Load 方法中,按照您的描述设置 FieldRenderer 的 Item 字段。如果需要使用此逻辑的子布局数量有限,这是最好的方法。
-
您可以创建一个 Item XFieldRenderer 子类,将 Item 绑定到 ItemS:
class ItemXFieldRenderer: FieldRenderer {
public ItemXFieldRenderer() {
Item = [code to retrieve ItemX];
}
}
然后,您可以在解决方案中任何想要从 ItemX 呈现字段的位置使用此控件。如果大量子布局需要使用此逻辑并且您可能需要绑定的项目数量非常有限,那么这是最好的方法。
您可以创建 FieldRenderer 的子类来解析字符串属性并使用逻辑将字符串值映射到正确的项目。
-
如果 ItemX 的路径是不变的,您可以在 Datasource 属性中设置完整路径,如下所示:
<sc:FieldRenderer runat="server" FieldName="Logo"
DataSource="/sitecore/context/home/some/item" />
您还可以使用相对路径。例如,如果上下文项有一个名为“Sources”的子文件夹,而该子文件夹又具有一个子项“Default”,则您可以使用以下语法在 FieldRenderer 中引用:
<sc:FieldRenderer runat="server" FieldName="Logo"
DataSource="sources/default" />
根据我的测试,数据源的评估不区分大小写,并且像“../..”和“//*[@@name='value']”这样的 Sitecore 查询表达式不起作用。
-
您可以使用数据绑定来强制 ASCX 读取属性,如本文中所建议的论坛主题 http://sdn.sitecore.net/Forum/ShowPost.aspx?postid=29371:
<sc:FieldRenderer id="myRenderer" FieldName="Logo"
DataSource=<%# ItemX.Paths.FullPath %> />
并在代码隐藏中添加
myRenderer.DataBind();
使用最后一种方法,您仍然使用代码隐藏,但哪个 FieldRenderer 使用哪个项目的决定现在包含在标记中。克里斯蒂安·哈格里德指出 https://stackoverflow.com/a/13427050/402949,您可以在子布局上调用 this.DataBind() 来强制 DataBind 在页面上的所有控件上递归执行。
-
您可以使用 ASP.NET 的 ExpressionBuilder 语法来集中数据源路径的位置。有三种方法可以做到这一点:
-
将您的路径放入 Web.config 中。将其添加到 Web.config 的 部分:
<add key="ItemX" value="/sitecore/content/path/to/itemx" />
然后将 DataSource 属性设置为:
DataSource=<%$ AppConfig: ItemX %>
-
将路径放置在 App_GlobalSettings 的 .resx 资源文件中。如果文件名为 Paths.resx,您可以使用以下语法访问其设置:
DataSource=<%$ Resources: Paths,ItemX %>
你可以建立一个表达式生成器 http://msdn.microsoft.com/en-us/library/system.web.compilation.expressionbuilder.aspx类来构建将字符串值转换为路径的逻辑。请注意,ExpressionBuilder 是在解析时评估的,因此您将无法访问 Sitecore 上下文。这看起来并不简单:表达式生成器需要在 Web.config 中引用,并且代码需要驻留在 App_Code 中。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)