设置 FieldRenderer 的 Item 或 DataSource 属性的好方法是什么? [英] What's a good way to set the Item or DataSource attribute of a FieldRenderer?

查看:22
本文介绍了设置 FieldRenderer 的 Item 或 DataSource 属性的好方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

场景是我有很多 FieldRenderer.这些应该输出来自不同地方的数据,一些来自项目 X,其他来自项目 Y.并且应该输出项目 Z 的属性.

The scenario is that I have a lot of FieldRenderers. These should output data from various places, some from item X and others from item Y. And should be outputting properties from item Z.

假设我有一个公共属性 ItemX 我想从中输出一个属性,以下任何一种都可以.但我没有得到任何输出:

Assuming I have a public property ItemX that I want to output a property from, any of the following would be OK. But I get no output by any of them:

<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 %>" />

如果我向它添加一个 ID MyFieldRenderer 并执行下面的丑陋部分,我会得到正确的输出:

If I add an ID MyFieldRenderer to it and do the ugly piece below, I get correct output:

MyFieldRenderer.Item = ItemX;

一定有更好的方法来做到这一点吗?我不确定这是 Sitecore 特定的问题还是 WebForms 的问题.

There must be a better way to do this? I'm not sure if this is a Sitecore-specific or WebForms question.

推荐答案

如果不使用隐藏代码,则无法将 FieldRenderer 的数据源设置为服务器端对象.这是 WebForms 工作方式的结果.Microsoft 知识库文章中描述了该问题:

It is not possible to set the datasource of a FieldRenderer to a server side object without using code behind. This is a consequence of how WebForms works. The issue is described in a Microsoft Knowledge Base article:

<%= ... %> 显示表达式等效于仅包含 Response.Write(...) 语句的嵌入代码块.这是显示单个字符串、int 变量或常量等信息的最简单方法.[...] 请记住,不能在服务器控件的属性中使用显示表达式.这是因为 .NET Framework 直接编译整个表达式,而不是将显示内容作为属性的值.

The <%= ... %> displaying expression is an equivalent of the embedded code block that contains only the Response.Write(…) statement. This is the simplest way to display information such as a single string, an int variable, or a constant. [...] Remember that the displaying expression cannot be used in the attributes of server controls. This is because the .NET Framework directly compiles the whole expression instead of the displaying content as the value to the attribute.

换句话说,.NET 想要编译 sc:FieldRenderer,因此无法访问 <%= ItemX.Paths.FullPath %> 的运行时内容.您可以通过尝试显示以更简单的形式查看此问题:

In other words, .NET wants to compile the sc:FieldRenderer, and so does not have access to the run-time contents of <%= ItemX.Paths.FullPath %>. You can see this issue in simpler form by trying to display:

<asp:TextBox runat="server" Text="<%= DateTime.Now.ToString() %>" />

在文本框中呈现 <%= DateTime.Now.ToString() %> .简而言之,除了服务器控件属性中的静态字符串之外,您无法获得任何其他内容.

which renders <%= DateTime.Now.ToString() %> inside the text box. In short, you cannot get anything other than a static string inside a server control attribute.

这个问题有几种可能的解决方案:

There are several possible solutions to this issue:

  1. 在您的 Page_Load 方法中,按照您的描述设置 FieldRenderer 的 Item 字段.如果需要使用此逻辑的子布局数量有限,这是最好的方法.

  1. In your Page_Load method, set the Item field of the FieldRenderer, as you describe. This is the best approach if the number of sublayouts that need to use this logic is limited.

您可以创建一个将 Item 绑定到 ItemX 的 ItemXFieldRenderer 子类:

You can create an ItemXFieldRenderer subclass that binds Item to ItemX:

 class ItemXFieldRenderer: FieldRenderer {
   public ItemXFieldRenderer() {
       Item = [code to retrieve ItemX];
   }
 }

然后,您可以在解决方案中的任何位置使用此控件,以便从 ItemX 呈现字段.如果大量子布局需要使用此逻辑并且您可能需要绑定的项目数量非常有限,则这是最好的方法.

Then you can use this control anywhere in your solution where you want to render a field from ItemX. This is the best approach if a large number of sublayouts need to use this logic and the number of items you might need to bind to is very limited.

您可以创建 FieldRenderer 的子类,用于解析字符串属性并使用逻辑将字符串值映射到正确的项目.

You could create a subclass of FieldRenderer that parses a string property and uses logic to map the string value to the correct item.

如果 ItemX 的路径是常量,您可以在 Datasource 属性中设置完整路径,如下所示:

If the path to ItemX is constant, you can set the full path in the Datasource property like this:

<sc:FieldRenderer runat="server" FieldName="Logo"
DataSource="/sitecore/context/home/some/item" />

您也可以使用相对路径.例如,如果上下文项有一个名为Sources"的子文件夹,而该子文件夹又具有一个子项Default",则您可以使用以下语法在 FieldRenderer 中进行引用:

You can also use a relative path. For example, if the context item has a child folder called "Sources", which in turn has a child item "Default", you could reference in your FieldRenderer with this syntax:

<sc:FieldRenderer runat="server" FieldName="Logo"
DataSource="sources/default" />

根据我的测试,数据源的评估不区分大小写,并且诸如../.."和///*[@@name='value']"之类的 Sitecore 查询表达式不起作用.

Per my testing, the evaluation of the datasource is case-insensitive, and Sitecore Query expressions like "../.." and "//*[@@name='value']" do not work.

您可以使用数据绑定来强制 ASCX 读取该属性,如本 论坛主题:

You can use databinding to force ASCX to read the property, as recommended in this Forums thread:

<sc:FieldRenderer id="myRenderer" FieldName="Logo" 
DataSource=<%# ItemX.Paths.FullPath %> />

并在代码隐藏中添加

myRenderer.DataBind(); 

使用最后一种方法,您仍然使用代码隐藏,但是现在标记中包含了哪个 FieldRenderer 使用哪个项目的决定.正如 Christian Hagelid 指出,您可以在子布局上调用 this.DataBind() 以强制 DataBind 在所有对象上递归执行页面上的控件.

With this last approach you are still using codebehind, but the decision of which FieldRenderer uses which item is now contained in the markup. And as Christian Hagelid points out, you can call this.DataBind() on the sublayout to force DataBind to execute recursively on all controls on the page.

您可以使用 ASP.NET 的 ExpressionBuilder 语法来集中数据源路径的位置.有以下三种方法:

You can use ASP.NET's ExpressionBuilder syntax to centralize the location of your datasource paths. There are three ways of doing this:

  • 将您的路径放在 Web.config 中.将此添加到 <AppSettings>Web.config 部分:

  • Places your paths in Web.config. Add this to the <AppSettings> section of Web.config:

<add key="ItemX" value="/sitecore/content/path/to/itemx"/>
然后将 DataSource 属性设置为:

<add key="ItemX" value="/sitecore/content/path/to/itemx" />
Then set the DataSource attribute to:

DataSource=<%$ AppConfig: ItemX %>

将路径放在 App_GlobalSettings 的 .resx 资源文件中.如果文件名为 Paths.resx,您可以使用以下语法访问其设置:

Place the paths in a .resx resource file in App_GlobalSettings. If the file is named Paths.resx, you can access its settings with this syntax:

DataSource=<%$ 资源:路径,ItemX %>

您可以构建一个 ExpressionBuilder 类来构建逻辑以将字符串值转换为路径.请注意, ExpressionBuilder 在解析时进行评估,因此您将无法访问 Sitecore 上下文.这看起来并不简单:表达式生成器需要在 Web.config 中引用,代码需要驻留在 App_Code 中.

You can build an ExpressionBuilder class to build logic to translate a string value to a path. Note that the ExpressionBuilder is evaluated at Parse time, so you will not have access to the Sitecore context. This does not look straightforward: the expression builder needs to be referenced in Web.config and the code needs to reside in App_Code.

这篇关于设置 FieldRenderer 的 Item 或 DataSource 属性的好方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆