Sim*_*eon 4 asp.net webforms sitecore sitecore6
场景是我有很多FieldRenderers.这些应该从各个地方输出数据,一些来自项目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 %>" />
Run Code Online (Sandbox Code Playgroud)
如果我MyFieldRenderer为它添加一个ID 并执行下面的丑陋部分,我会得到正确的输出:
MyFieldRenderer.Item = ItemX;
Run Code Online (Sandbox Code Playgroud)
必须有更好的方法来做到这一点?我不确定这是Sitecore特定的还是WebForms问题.
如果不使用代码,则无法将FieldRenderer的数据源设置为服务器端对象.这是WebForms工作方式的结果.Microsoft知识库文章中描述了此问题:
显示表达式的<%= ...%>等效于仅包含Response.Write(...)语句的嵌入式代码块.这是显示单个字符串,int变量或常量等信息的最简单方法.[...] 请记住,显示表达式不能用于服务器控件的属性.这是因为.NET Framework直接编译整个表达式而不是显示内容作为属性的值.
换句话说,.NET想要编译sc:FieldRenderer,因此无法访问<%= ItemX.Paths.FullPath%>的运行时内容.您可以通过尝试显示以更简单的形式查看此问题:
<asp:TextBox runat="server" Text="<%= DateTime.Now.ToString() %>" />
Run Code Online (Sandbox Code Playgroud)
在文本框中呈现<%= DateTime.Now.ToString()%>.简而言之,除了服务器控件属性中的静态字符串之外,您无法获得任何其他内容.
这个问题有几种可能的解决方案:
在Page_Load方法中,如您所述,设置FieldRenderer的Item字段.如果需要使用此逻辑的子布局数量有限,这是最佳方法.
您可以创建一个将Item绑定到ItemX的ItemXFieldRenderer子类:
class ItemXFieldRenderer: FieldRenderer {
public ItemXFieldRenderer() {
Item = [code to retrieve ItemX];
}
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以在解决方案中的任何位置使用此控件,以便从ItemX渲染字段.如果大量子布局需要使用此逻辑,并且可能需要绑定的项目数量非常有限,则这是最佳方法.
您可以创建FieldRenderer的子类,该子类解析字符串属性并使用逻辑将字符串值映射到正确的项目.
如果ItemX的路径是常量,您可以在数据源属性中设置完整路径,如下所示:
<sc:FieldRenderer runat="server" FieldName="Logo"
DataSource="/sitecore/context/home/some/item" />
Run Code Online (Sandbox Code Playgroud)
您还可以使用相对路径.例如,如果上下文项目具有名为"Sources"的子文件夹,而子文件夹又具有子项"Default",则可以使用以下语法在FieldRenderer中引用:
<sc:FieldRenderer runat="server" FieldName="Logo"
DataSource="sources/default" />
Run Code Online (Sandbox Code Playgroud)
根据我的测试,数据源的评估不区分大小写,Sitecore查询表达式如"../ .."和"//*[@@ name ='value']"不起作用.
您可以使用数据绑定强制ASCX读取属性,如此论坛主题中所建议的那样:
<sc:FieldRenderer id="myRenderer" FieldName="Logo"
DataSource=<%# ItemX.Paths.FullPath %> />
Run Code Online (Sandbox Code Playgroud)
在代码隐藏中,添加
myRenderer.DataBind();
Run Code Online (Sandbox Code Playgroud)
使用最后一种方法,您仍然使用代码隐藏,但是决定哪个FieldRenderer使用哪个项目现在包含在标记中.正如Christian Hagelid 指出的那样,您可以在子布局上调用this.DataBind()来强制DataBind以递归方式对页面上的所有控件执行.
您可以使用ASP.NET的ExpressionBuilder语法来集中数据源路径的位置.有三种方法可以做到这一点:
将路径放在Web.config中.将其添加到Web.config的<AppSettings>部分:
<add key="ItemX" value="/sitecore/content/path/to/itemx" />
然后将DataSource属性设置为:
DataSource=<%$ AppConfig: ItemX %>
将路径放在App.GlobalSettings中的.resx资源文件中.如果文件名为Paths.resx,则可以使用以下语法访问其设置:
DataSource=<%$ Resources: Paths,ItemX %>
您可以构建一个ExpressionBuilder类来构建逻辑以将字符串值转换为路径.请注意,ExpressionBuilder在Parse时进行评估,因此您无权访问Sitecore上下文.这看起来并不简单:表达式构建器需要在Web.config中引用,代码需要驻留在App_Code中.