Как загрузить элемент управления, который использует VaryByControl OutputCache, указав значения для свойств - PullRequest
5 голосов
/ 04 июля 2011

У меня есть пользовательский элемент управления, который должен использовать кэширование, с 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 в файле code-behind имеет свойство 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>

Два тега <xxx:TestControl> правильно загружают экземпляры TestControl с Testустановив ожидаемое значение, я могу несколько раз обновить браузер и увидеть, как кеш правильно выполняет свою работу.

Теперь я хотел бы заполнить <asp:PlaceHolder ID="Suport" /> некоторыми экземплярами TestControl,используя переменные Test значения, которые должны выиграть от правильного кэширования.Я пытаюсь использовать метод LoadControl, но не могу найти способ указать значение для свойства Test.Я ожидаю, что такой метод существует, после того, как все asp.net код, загружающий страницу .aspx, удастся найти правильный кешированный элемент управления.Все, что я получаю, это экземпляр PartialCachingControl без инициализации CachedControl, и во время выполнения отрисованный TestControl показывает Test имеет значение по умолчанию 0.

Вот как мой .aspx *Обработчик событий 1037 * выглядит следующим образом:

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

Хмм, пока нет ответов.Я запустил награду, надеюсь, она получит немного больше внимания.

Ответы [ 3 ]

3 голосов
/ 31 октября 2012

Вы должны поменять 2 строки, чтобы ваш код работал:

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

Как только вы добавляете элемент управления, кэшированный элемент управления инициализируется.

Е.Г.

3 голосов
/ 14 июля 2011

Чтобы получить элемент управления в полном жизненном цикле страницы, его нужно добавить в событие 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;
}

Поскольку выходные данные кэшируются для каждого элемента управления, вы не можете изменитьконтроль, пока кэш не очищен.Если вы хотите изменить значение и восстановить контент, вам нужно либо очистить кеш, либо создать новый элемент управления (с новым идентификатором).Один из способов очистки кеша - использовать вместо него VaryByCustom и генерировать ключ кеша, который изменяется при изменении значения Test.

Также не забудьте реализовать интерфейс INamingContainer в вашем элементе управления test, чтобы избежать конфликтов имен между различнымиобъекты.Для этого просто добавьте интерфейс к элементу управления, например:

public class TestControl: WebControl, INamingContainer {}
2 голосов
/ 14 июля 2011

Я думаю, что вы неправильно поняли свойство VarByControl, оно говорит не кэш-памяти о необходимости изменения свойства элемента управления, а об идентификаторе элементов управления на странице. Вот текст из MSDN :

Для свойства VaryByControl заданы полностью определенные идентификаторы элемента управления, где идентификатор представляет собой объединение идентификаторов элемента управления, начиная с родительского элемента управления верхнего уровня и ограниченного знаком доллара ($).

В вашем случае вы можете установить VaryByCustom вместо VaryByControl, сгенерировать ключ кеша из значения свойства Test и изменить его, если он изменится.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...