01/12/2008

LoadControl

Home

Czy poniższy kod zawierający wywołanie metody LoadControl wydaje się wam poprawny? Jeśli tak to zapraszam do dalszej lektury.

protected void Page_Load(object sender, EventArgs e)
{
    ...
    Control control = LoadControl("~/MySimpleUserControl.ascx");
    PlaceHolder1.Controls.Add(control);

    ((MySimpleUserControl)control).BackColor = Color.Yellow;
    ...
}
Niestety ale kod ten będzie działał poprawnie tylko do momentu kiedy dla kontrolki zostanie włączony mechanizm Output Cache, na przykład w następujący sposób:

<%@ OutputCache Duration="60" VaryByParam="None" %>
W takim przypadku, przy następnym ładowaniu strony, na której umieszczono kontrolkę, pojawi się wyjątek InvalidCastException z komunikatem: "Unable to cast object of type ‘System.Web.UI.PartialCachingControl’ to type ‘MySimpleUserControl’.". Dzieje się tak ponieważ metoda LoadControl, w przypadku kiedy włączone jest cache'owanie dla kontrolki, zwraca obiekt klasy PartialCachingControl, a nie klasy MySimpleUserControl jak mogłoby się wydawać. W takie sytuacji do kontrolki możemy się dostać przez właściwość PartialCachingControl.CachedControl. Poprawny kod powinien, więc wyglądać tak:

protected void Page_Load(object sender, EventArgs e)
{
    ...
    Control control = LoadControl("~/MySimpleUserControl.ascx");
    PlaceHolder1.Controls.Add(control);

    MySimpleUserControl c = control as MySimpleUserControl;
    if(c == null)
    {
        PartialCachingControl pc = control as PartialCachingControl;
        c = pc.CachedControl as MySimpleUserControl;
    }

    if(c != null)
       c.BackColor = Color.Yellow;
    ...
}
Dodatkowe sprawdzenie if(c != null) jest potrzebne ponieważ właściwość PartialCachingControl.CachedControl zwróci null jeśli kontrolka znajduje się już w cache'u. Innymi słowy wartość różna od null zostanie zwrócona tylko wtedy kiedy kontrolka nie została jeszcze umieszczona w cache albo zawartość cache przestała być ważna.

Należy również pamiętać aby odwołanie do PartialCachingControl.CachedControl było zawsze poprzedzone umieszczeniem kontrolki na stronie np.: PlaceHolder1.Controls.Add(control);. W przeciwnym wypadku właściwość PartialCachingControl.CachedControl zawsze zwróci null.

W przypadku kiedy korzystamy z cache'owania i mamy na stronie statycznie osadzone kontrolki również należy zachować ostrożność. Jeśli kontrolka zostanie pobrana z cache to nie zostanie zainicjowana i nie możemy w związku z tym odwołać się do niej w kodzie naszej strony. Oczywiście jest to jak najbardziej prawidołe zachowanie - na tym polega idea mechanizmu Output Cache.

0 comments:

Post a Comment