W dwóch poprzednich rozdziałach nauczyliśmy się tworzyć własne kontrolki ASP.NET. dzięki środowisku Visual Studio 2005 zadanie to jest proste nawet dla początkujących użytkowników. Jednak bardziej zaawansowani programiści po pewnym czasie stwierdzą, że możliwości kontrolek, budowanych z gotowych elementów okazują się niewystarczające. Każdy pojedynczy element, wchodzący w skład naszej kontrolki, charakteryzuje się pewnym specyficznym zachowaniem. Najlepszym sposobem, na posiadanie pełnej kontroli nad zachowaniem i wyglądem tworzonych przez nas kontrolek, jest umieszczenie wszystkich informacji dotyczących wyżej wymienionych aspektów w kodzie w językach C#, J# lub Visual Basic. Tego typu kontrolki w literaturze opisywane są jako: „Custom Render Controls”.
Próbę stworzenia nowej, w pełni renderowanej kontrolki, rozpocznijmy od stworzenia w Visual Studio nowego projektu Web Control Library (w Visual Studio 2005 nie wiadomo czemu, schemat dla tego projektu, przy wykorzystaniu języka C#, odnaleźć możemy w zakładce Project Types -> C# -> Windows -> Web Control Library. Stwórzmy także przykładową stronę ASP.NET na której będziemy mogli testować działanie kontrolki.
Główną metodą w kodzie naszego programu jest, jak zapewnie zdążyliście się domyślić, metoda o nazwie: Render(HtpmTextWriter output). Wykorzystywana była ona również w projekcie stworzonym w poprzednim rozdziale kursu. W tamtym przypadku, wykorzystywana była ona jednak wyłącznie, do prezentacji na ekranie jednej z właściwości obiektu. Poniższy kod prezentuje nieco bardziej zaawansowane wykorzystanie wspomnianej metody.
protected override void Render(HtmlTextWriter output)
{
output.Write("<h2>Moja własna
kontrolka</h2>");
output.WriteBeginTag("INPUT");
output.WriteAttribute("value",
"Przycisk");
output.WriteAttribute("type", "button");
output.WriteAttribute("onclick",
"javascript:alert('Hello world!')");
output.WriteEndTag("INPUT");
}
Pierwszą czynnością, którą będzie wykonywać powyższy kod, po umieszczeniu kontrolki na formatce, jest wypisanie w oknie przeglądarki napisu: „Moja własna kontrolka”. Wykorzystywana jest do tego poznana już poprzednio metoda „Write”, klasy HttpTextWriter. Następnie rozpoczynamy renderowanie nowego elementu, wykorzystując do tego metodę „WriteBeginTag”, z odpowiednim parametrem. Generowanie elementu kończy metoda „WriteEndTag”. Między wspomnianymi, znajdują się natomiast wywołania metody WrieAttribute, ustawiające poszczególne właściwości tworzonego obiektu. W powyższym kodzie widzimy, że po wyświetleniu kontrolki, na ekranie pojawi się obiekt „button”, o nazwie „Przycisk”. Po naciśnięciu przycisku, zostanie natomiast uruchomiony odpowiedni kod JavaScript (właściwość: „onclick”).
Umieśćmy teraz naszą kontrolkę na formatce ASP.NET (informacje na ten temat zawarte są w poprzednim rozdziale), a następnie spróbujmy uruchomić formatkę w oknie przeglądarki. Jeżeli wszystko przebiegło pomyślnie efekt powinien być następujący.
Po naciśnięciu na przycisk uruchamia się kod, wykonywany po stronie klienta.
Zamknijmy teraz okienko „Hello world” i kliknijmy prawym przyciskiem myszy w oknie przeglądarki. Z menu kontekstowego wybierzmy opcję o nazwie „Pokaż źródło” (lub podobnie, w zależności od używanego browsera). Wygenerowany przez naszą kontrolkę kod prezentował się będzie następująco:
<h2>Moja własna
kontrolka</h2><INPUT value="Przycisk"
type="button" onclick="javascript:alert('Hello world!')"</INPUT>
Wszystkie kontrolki, tworzone do tej pory, do przechowywania informacji używały właściwości składających się na nie elementów. Ponieważ składniki renderowanej kontrolki, generowane są bezpośrednio w kodzie, do przechowywania informacji musimy użyć ViewState’a. Jest to właściwość strony, przechowująca informacje bezpośrednio w generowanej strony. Wyświetlając źródła każdej strony, wygenerowanej dynamicznie za pomocą technologii ASP.NET, będziemy mogli odnaleźć następujący ciąg znaków.
<div>
<input
type="hidden" name="__VIEWSTATE" id="__VIEWSTATE"
value="/wEPDwULLTE0NzkzODYxNzJkZL1nw3GkfajYBqDHaUeW1QmKpYYw"
/>
</div>
Informacje zawarte w ViewState’cie są oczywiści zaszyfrowane. Poniższy kod, zawiera przykład przechowywania właściwości kontrolki o nazwie „Text”, wykorzystując do tego celu wspomnianą technikę.
get
{
if (ViewState["Tekst"]
!= null)
{
return ViewState["Text"].ToString();
}
else
{
return null;
}
}
set
{
ViewState["Text"] = value;
}
}
Kontrolki, składane z gotowych elementów do komunikacji z użytkownikiem wykorzystują właściwości obiektów, wchodzących w ich skład. W przypadku kontrolek renderowanych sprawa jest nieco trudniejsza. W zależności od rodzaju zdarzenia, odpowiedni kod musi być wywołany w kodzie kontrolki, bądź też po stronie klienta, używając do tego odpowiedniego skryptu. W dalszej części rozdziału zostanie omówiony pierwszy przypadek. Kod wykonywany jest wówczas w momencie wystąpienia zdarzenia PostBack, tzn. w momencie, w którym formatka jest odsyłana do serwera (na przykład, po wypełnieniu formularza, i naciśnięciu przycisku „Wyślij”). Prezentuje to kod poniższy kod.
[DefaultProperty("Text")]
[ToolboxData("<{0}:WebCustomControl1
runat=server></{0}:WebCustomControl1>")]
public class WebCustomControl1
: WebControl
{
//private string text;
public EventHandler Change;
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("")]
public string Text
{
get
{
if (ViewState["Tekst"]
!= null)
{
return ViewState["Tekst"].ToString();
}
else
{
return null;
}
}
set
{
ViewState["Tekst"] = value;
this.OnChange(EventArgs.Empty);
}
}
protected override void Render(HtmlTextWriter output)
{
output.Write("<h2>Moja
własna kontrolka</h2>");
output.WriteBeginTag("INPUT");
output.WriteAttribute("value",
this.Text);
output.WriteAttribute("type", "button");
output.WriteAttribute("onclick",
"javascript:alert('Hello world!')");
output.WriteEndTag("INPUT");
}
protected virtual void OnChange(EventArgs e)
{
if (this.Change != null)
{
Change(this, e);
}
}
}
Nowe elementy w naszej kontrolce, to metoda o nazwie: OnChange, która będzie wykonywana po każdej próbie zmiany tekstu oraz właściwość klasy EventHandler. Dodatkowy kod musimy dodać także w kodzie strony, na której znajduje się kontrolka.
protected void Page_Load(object sender, EventArgs e)
{
this.WebCustomControl1_1.Change += new EventHandler(this.text_Changed);
}
private void
text_Changed(object sender, System.EventArgs e)
{
this.Response.Write("Nastąpiła
zmiana tekstu...");
}
Umieśćmy jeszcze na formatce, przycisk po naciśnięciu, którego, następowała będzie zmiana właściwości „Text” naszej kontrolki.
protected void Button1_Click(object sender, EventArgs e)
{
this.WebCustomControl1_1.Text = "Nowy tekst...";
}
Po uruchomieniu, strona wyglądać będzie następująco.
Naciśnięcie przycisku spowoduje wykonanie kodu po stronie serwera.