5

キャッシュを使用する必要があるユーザーコントロールがありますVaryByControl。ファイルは次の.ascxようになります:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="TestControl.ascx.cs" Inherits="mynamespace.TestControl" %>
<%@ OutputCache Duration="10" Shared="true" VaryByControl="Test" %>
<p id="SomeText" runat="server">Nothing</p>

コードビハインドファイルのTestControlクラスには、段落を次のように埋めるint Test {...}プロパティとイベントハンドラーがあります。Page_Load()SomeText

SomeText.InnerText = string.Format(@"Test={0} at {1}", Test, DateTime.Now)

次のようなファイルがあり.aspxます。

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="TestPage.aspx.cs" Inherits="mynamespace.TestPage" %>
<%@ Register TagPrefix="xxx" TagName="TestControl" Src="Controls\TestControl.ascx" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <xxx:TestControl Test="6" runat="server" />
    <xxx:TestControl Test="7" runat="server" />
    <hr />
    <asp:PlaceHolder ID="Suport" runat="server" />
</body>
</html>

2つの<xxx:TestControl>タグは、期待値に設定されたのインスタンスを適切にロードTestControlしますTest。ブラウザーを数回更新でき、キャッシュが適切に機能していることを確認できます。

ここで、さまざまな値を使用して<asp:PlaceHolder ID="Suport" />、のいくつかのインスタンスで埋めたいと思います。これらはすべて、適切なキャッシュの恩恵を受けるはずです。メソッドを使用しようとしていますが、プロパティの値を指定する方法が見つかりません。ページをロードするすべてのコードが適切なキャッシュされたコントロールを見つけることができた後、そのようなメソッドが存在することを期待しています。私が取得するのは、初期化されていないのインスタンスであり、実行時にレンダリングされたショーのデフォルト値はです。TestControlTestLoadControlTestasp.net.aspxPartialCachingControlCachedControlTestControlTest0

これは私の.aspx Page_Load()イベントハンドラーがどのように見えるかです:

protected void Page_Load(object sender, EventArgs e)
{
    PartialCachingControl tc = (PartialCachingControl) LoadControl(@"Controls\TestControl.ascx");
    if (tc.CachedControl != null)
        ((TestControl)tc.CachedControl).Test = 67;            
    Suport.Controls.Add(tc);
}

編集

ページ全体をキャッシュすることで問題を回避することはできますが、この方法でそれを行う方法が見つからないのは奇妙に思えます。特に、ASPXファイルを介してコントロールを呼び出すと期待どおりに機能するため(方法があることを証明します)。

編集2

うーん、今のところ答えはありません。私は賞金を始めました、うまくいけばそれはもう少し注目を集めるでしょう。

4

3 に答える 3

3

コードを機能させるには、2行を入れ替える必要があります。

PartialCachingControl tc = (PartialCachingControl) LoadControl(@"Controls\TestControl.ascx");
Suport.Controls.Add(tc);
if (tc.CachedControl != null)
    ((TestControl)tc.CachedControl).Test = 67;            

コントロールを追加するとすぐに、キャッシュされたコントロールが初期化されます。

例えば

于 2012-10-31T13:09:53.067 に答える
3

コントロールを完全なページ ライフ サイクルに参加させるには、それを Load に追加するのではなく、Init イベントまたは CreateChildControls メソッドに追加する必要があります。VaryByControl が機能するには完全修飾されたコントロール識別子が必要なため、ページ サイクルが始まる前に初期化する必要があります。

これに似たもの:

protected override void OnInit(EventArgs e) {
    var testControl = LoadControl(@"TestControl.ascx");
    testControl.ID =  "TestControl";
    Suport.Controls.Add(testControl);
    base.OnInit(e);
}

protected override void OnLoad(EventArgs e) {
    TestControl testControl = GetTestControl("TestControl");
    if(testControl != null){ //If it is null it is cached and can not be changed
        testControl.Test = 242;
    }
    base.OnLoad(e);
}

private TestControl GetTestControl(string name) {
    var control = this.Suport.FindControl(name);
    var partialCachedControl = control as PartialCachingControl;
    if(partialCachedControl != null) {
        control = partialCachedControl.CachedControl;
    }
    return control as TestControl;
}

出力はコントロールごとにキャッシュされるため、キャッシュがクリアされるまでコントロールを変更することはできません。値を変更してコンテンツを再生成する場合は、キャッシュをクリアするか、新しいコントロールを (新しい ID で) 作成する必要があります。キャッシュをクリアする 1 つの方法は、代わりに VaryByCustom を使用し、Test-value が変更された場合に変更されるキャッシュ キーを生成することです。

また、異なるオブジェクト間の名前の競合を避けるために、テスト コントロールに INamingContainer インターフェイスを実装することを忘れないでください。これを行うには、次のようにインターフェイスをコントロールに追加します。

public class TestControl: WebControl, INamingContainer {}
于 2011-07-14T09:18:44.063 に答える