4

シナリオは、私がたくさんの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 %>" />

IDを追加しMyFieldRendererて以下の醜い部分を実行すると、正しい出力が得られます。

MyFieldRenderer.Item = ItemX;

これを行うためのより良い方法があるはずですか?これがSitecore固有の質問なのかWebFormsの質問なのかわかりません。

4

3 に答える 3

7

コードビハインドを使用せずに、FieldRendererのデータソースをサーバー側オブジェクトに設定することはできません。これは、WebFormsがどのように機能するかの結果です。この問題は、Microsoftサポート技術情報の記事で説明されています。

<%= ...%>表示式は、Response.Write(…)ステートメントのみを含む埋め込みコードブロックと同等です。これは、単一の文字列、int変数、定数などの情報を表示する最も簡単な方法です。[...]表示式はサーバーコントロールの属性では使用できないことに注意してください。これは、.NET Frameworkが、属性の値としてコンテンツを表示するのではなく、式全体を直接コンパイルするためです。

つまり、.NETはsc:FieldRendererをコンパイルする必要があるため、<%= ItemX.Paths.FullPath%>の実行時コンテンツにアクセスできません。次のように表示すると、この問題をより簡単な形式で確認できます。

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

<%= DateTime.Now.ToString()%>をテキストボックス内にレンダリングします。つまり、サーバー制御属性内で静的文字列以外のものを取得することはできません。


この問題にはいくつかの解決策があります。

  1. Page_Loadメソッドで、説明どおりにFieldRendererのItemフィールドを設定します。これは、このロジックを使用する必要のあるサブレイアウトの数が制限されている場合に最適なアプローチです。

  2. ItemをItemXにバインドするItemXFieldRendererサブクラスを作成できます。

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

    次に、ItemXからフィールドをレンダリングするソリューションのどこでも、このコントロールを使用できます。これは、多数のサブレイアウトでこのロジックを使用する必要があり、バインドする必要のあるアイテムの数が非常に限られている場合に最適なアプローチです。

  3. 文字列プロパティを解析し、ロジックを使用して文字列値を正しいアイテムにマップするFieldRendererのサブクラスを作成できます。

  4. 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クエリ式は機能しません。

  5. このフォーラムスレッドで推奨されているように、データバインディングを使用して、ASCXにプロパティを強制的に読み取ることができます。

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

    そして、コードビハインドで、

    myRenderer.DataBind(); 
    

    この最後のアプローチでは、まだコードビハインドを使用していますが、どのFieldRendererがどのアイテムを使用するかの決定がマークアップに含まれるようになりました。また、Christian Hagelidが指摘しているように、サブレイアウトでthis.DataBind()を呼び出すと、ページ上のすべてのコントロールでDataBindが再帰的に実行されます。

  6. ASP.NETのExpressionBuilder構文を使用して、データソースパスの場所を一元化できます。これを行うには3つの方法があります。

    • パスを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は解析時に評価されるため、Sitecoreコンテキストにアクセスできないことに注意してください。これは単純ではありません。式ビルダーはWeb.configで参照され、コードはApp_Codeに存在する必要があります。

于 2012-11-16T23:25:38.033 に答える
4

多くのFieldRendererコントロールがあり、マークアップ内にロジックを含めたい場合は、<%#...%>式を使用して、this.DataBind();を呼び出すことができます。Page.Loadの最後にあります。これにより、ユーザーコントロール内のすべてのコントロールがバインドされます。

于 2012-11-17T02:21:24.397 に答える
1

コードビハインドではなく、MVCスタイルのようにフロントエンドでこれを実行できるようにしたいことは理解していますが、そのシナリオでは、フロントエンドのFieldRendererコントロールが適切なツールではない可能性があります。私は明らかにあなたがあなたの答えに書いたコードを見ました、しかしなぜそれならこれをしないのですか、すべてフロントエンドで:

<%= FieldRenderer.Render(item, "field name") %>

例えば

<%= FieldRenderer.Render(ItemX, "Logo") %>
于 2012-11-20T20:20:14.217 に答える