10/12/2008

Czemu zdarzenia nie działają???

Home

Ostatnio pomogłem rozwiązać dwa problemy z "nie działającymi" zdarzeniami. Jak to najczęściej bywa, znając rozwiązanie, problem wydaje się banalnie prosty. Ponieważ jednak dojście do rozwiązania nie zawsze jest już tak proste postanowiłem napisać ten post.

Ogólnie problem został mi przedstawiony mniej więcej w taki sposób (luźny cytat): Podczepiłem się pod zdarzenia kilku kontrolek ale po wykonaniu post back'a do strony, metody obsługi zdarzeń nie są wołane.

W obu wspomnianych sytuacjach obserwowany efekt był taki sam (metody obsługi zdarzeń nie były wołane), natomiast przyczyna błędu troszeczkę inna. Błędu, ponieważ to oczywiście nie bug w maszynerii ASP.Net tylko najzwyklejszy w świecie błąd programisty.

Problem numer 1

W pierwszym przypadku programista dynamicznie tworzył kontrolkę, subskrybował jej zdarzenia, a następnie dodawał ją do strony. Dla ustalenia uwagi przyjmijmy, że była to kontrolka ListBox. Opisywany kod mógł więc wyglądać następująco:
...
ListBox lb = new ListBox();
lb.AutoPostBack = true;
lb.SelectedIndexChanged += new EventHandler(lb_SelectedIndexChanged);
lb.Items.Add("a");
lb.Items.Add("b");
lb.Items.Add("c");

this.Panel.Controls.Add(lb);
...
Sam w sobie, kod ten jest jak najbardziej poprawny. Błąd polegał na tym, że kod ten był wykonywany tylko w przypadku inicjalnego odwołania do strony. W przypadku post back'a czyli kiedy właściwość IsPostBack była równa true już nie. A skoro kontrolka nie została utworzona to zdarzenie nie mogło zostać wygenerowane.

Problem numer 2

W drugim przypadku programista używał statycznie osadzonej na stronie kontrolki DataList, zasilał ją danymi i wołał metodę DataBind. Kod strony przypominał koncepcyjnie kod poniżej:
...
this.DataList.DataSource = new string[] { "a", "b", "c" };
this.DataList.DataBind();
...
...
<asp:DataList ID="DataList" runat="server" EnableViewState="false">
   <ItemTemplate>
      <asp:Button ID="Button" runat="server" Text="<%# Container.DataItem %>" OnClick="OnClick" />
   </ItemTemplate>
</asp:DataList>
...
Podobnie jak wcześniej, strona nie działała tak jak powinna, ponieważ w przypadku post back'a nie była wołana metoda DataBind kontrolki DataList i przyciski nie były tworzone i w związku z tym zdarzenia nie mogły zostać wygenerowane. W tym jednak przypadku, pośrednią przyczyną błędu był fakt, że View State został wyłączony. Gdyby był włączony, przyciski zostałyby odtworzone na jego podstawie.

Wnioski

Konkluzja jest bardzo prosta. W przypadku dynamicznego tworzenia kontrolek, czy to bezpośrednio czy to przy okazji użycia kontrolek data bound zawsze należy pamiętać aby dynamiczne kontrolki były tworzone nie tylko przy inicjalnym odwołaniu do strony ale również przy kolejnych.

0 comments:

Post a Comment