Artykuł pochodzi w serii przygotowań do egzaminu 70-562 ASP.NET.
Dzisiaj powiemy sobie o podstawowych kontrolkach (tytuł mógłby mylić :D ) których możemy użyć na naszej stronie. Dokładnie będą to: Literal, Table, TableRow, TableCell, Image, ImageButton, ImageMap, Calendar, FileUpload, Panel, MultiView, View, Wizard.
Kontrolka Literal
Kontrolka ta jest bardzo podobna do kontroli Label, ponieważ odpowiada za wyświetlanie statycznego tekstu na stronie. Nie dziedziczy ona po WebControl. Kontrolka ta nie wprowadza praktycznie żadnej dodatkowej funkcjonalności nawet nie jest żadnym znacznikiem html dzięki czemu m.in nie możemy do niej zastosować żadnego stylu. Spójrzmy na krótki przykład użycia:
1: //C#
2: protected void Page_Load(object sender, EventArgs e)
3: {
4: Literal1.Text =
5: @"This is an <font size=7>example</font><script>alert(""Hi"");</script>";
6: Literal2.Text =
7: @"This is an <font size=7>example</font><script>alert(""Hi"");</script>";
8: Literal3.Text =
9: @"This is an <font size=7>example</font><script>alert(""Hi"");</script>";
10: Literal1.Mode = LiteralMode.Encode;
11: Literal2.Mode = LiteralMode.PassThrough;
12: Literal3.Mode = LiteralMode.Transform;
13: }
Widzimy tutaj, że kontrolka ta może zostać uruchomiana w różnych trybach np. Encode spowoduje, że treść jest wyświetlana ze wszystkimi znacznikami i skryptami czyli tak jak Bóg stworzył a już PassThrough spowoduje, że treść zostanie zinterpretowana przez przeglądarkę.
Kontrolki Table, TableRow i TableCell
Słynne tabelki używane pewnie od początku istnienia html możemy używać nie tylko do wyświetlania danych tabelarycznych ale również są pomocne przy układzie grafiki na stornie itd. Każdemu kto choć trochę zna html’a znane są znaczniki <table>, <tr> i <td>. W asp.net tworzymy i zarządzamy tabelami bez tych znaczników. Tutaj również możemy wyświetlać przy pomocy tabel, statyczne informacje na stronie ale prawdziwą zaletą w asp jest to, że możemy tworzyć dynamicznie tabele w runtime. Kiedy mamy zamiar tylko wyświetlać statyczne informacje rozważymy używanie klasycznego html’a. Oczywiście jeżeli tych danych mamy więcej, potrzebujemy mieć większej kontroli nad nimi to użyjemy do tego celu innych kontrolek typu Repeater czy GridView.
Jak dodać dynamicznie wiersze i kolumny do kontrolki Table? Służą oczywiście do tego TableCell i TableRow. Sam Visual Studio wspiera stworzenie tabeli poprzez “wyklikanie" ale co jeśli byśmy chcieli, żeby podczas ładowania strony stworzyła nam się tabelka. Spójrzmy na poniższy kod który mam nadzieje nie wymaga komentarza.
1: //C#
2: protected void Page_PreInit(object sender, EventArgs e)
3: {
4: Table1.BorderWidth = 1;
5: for (int row = 0; row < 5; row++)
6: {
7: TableRow tr = new TableRow();
8: for (int column = 0; column < 3; column++)
9: {
10: TableCell tc = new TableCell();
11: tc.Text = string.Format("Row:{0} Cell:{1}", row, column);
12: tc.BorderWidth = 1;
13: tr.Cells.Add(tc);
14: }
15: Table1.Rows.Add(tr);
16: }
17: }
Kontrolka Image
Tutaj podobnie ja w tabelkach jeżeli na stornie potrzebujemy coś więcej niż jeden statyczny obrazek to zamiast znacznika <img> użyjemy kontrolki Image. Pozwala ona zarządzać danym obrazkiem lub obrazkami choć suma sumarum kontrolka ta zostanie zrenderowana jako znacznik <img>. Najważniejszą właściwością jej jest ImageUrl która wskazuje ścieżkę do pliku. Również wartą uwagi jest właściwość AlternateText która ustawia określony tekst zamiast obrazka bo np. przeglądarka nie obsługuje obrazków czy też właściwość ImageAlign która dostosowuje obraz w stosunku do innych elementów na stornie. Dodatkowo ustawiając właściwość DescriptionUrl ustawiamy w znaczniku atrybut longdesc a używając GenerateEmptyAlternateText wstawiamy atrybut alt=. Przykład wczytania obrazka podczas ładowania strony oraz ustawienie podstawowych właściwosci pokazuje poniższy kod:
1: //C#
2: protected void Page_Load(object sender, EventArgs e)
3: {
4: Image1.ImageUrl = "images/whale.jpg";
5: Image1.DescriptionUrl = "WhaleImageDescription.htm";
6: Image1.AlternateText = "This is a picture of a whale";
7: }
Kontrolka ImageButton
Podstawowa różnicą jaka się od razu narzuca jest to, że Image w przeciwieństwie do ImageButton nie obsługuje zdarzenia Click. To daje nam oczywiście o wiele większe możliwości. Kontrolka ta dziedziczy bezpośrednio z Image i jest ona zrenderowana przez przeglądarkę do znacznika <input type=”image”>. Dziedzicząc po Image ma ona te same właściwości, które nakreśliłem poprzednio. Spójrzmy na praktyczny przykład wykorzystania tej kontrolki. Kod poniżej po kliknięciu w obrazek ustawia jego alternatywny tekst na współrzędne kliknięcia.
1: //C#
2: public partial class ImageButton_Control : System.Web.UI.Page
3: {
4: protected void Page_Load(object sender, EventArgs e)
5: {
6: ImageButton1.ImageUrl = "images/redblue.jpg";
7: ImageButton1.AlternateText =
8: "This is a button. The left side is red. The right is blue.";
9: }
10: protected void ImageButton1_Click(object sender, ImageClickEventArgs e)
11: {
12: ImageButton1.AlternateText =
13: string.Format("Button Clicked at {0},{1}", e.X, e.Y);
14: }
15: }
Kontrolka ImageMap
Znamy już różnice podstawową pomiędzy kontrolkami Image a ImageButton. Co więc nowego wnosi nam kontrolka ImageMap w stosunku do ImageButton? To, że na obrazek dzielimy na pewne obszary (hot spoty) i w zależności gdzie klikniemy możemy dostać inną akcje. Kontrolka ta również dziedziczy z Image a co za tym idzie ma po niej to co najlepszy (czytaj wcześniej opisane właściwości :) ). W kodzie źródłowym jest ona zdefiniowana jako <asp:ImageMap> z zagnieżdżonymi hot spotami.
Hot spoty mogą być zdefiniowane jako: CircleHotSpot, RectangleHotSpot, i Polygon-HotSpot. Sam hot spot ma również takie właściwości jak AlternateText, NavigateUrl itp. Dodatkowo ma również metodę HotSpotMode która definiuje zachowanie po kliknięci w dany “gorący obszar”. Jakie one mogą być? Np. PostBack, Navigate. Może być również tryb Inactive który oznacza, że nie ma być wykonane nic po kliknięciu w wybrany obszar.
Poniższy kod pokazuje jak w kodzie można wykorzystać tą kontrolkę i hot spoty. Jest na stornie Label i do niego po kliknięciu w dany obszar zostaje przypisany kolor prostokąta. Spójrzmy na kod i zrzut ze storny:
1: //C#
2: public partial class HotSpotControl : System.Web.UI.Page
3: {
4: protected void Page_Load(object sender, EventArgs e)
5: {
6: ImageMapStopLight.ImageUrl = "images/stoplight.jpg";
7: ImageMapStopLight.AlternateText = "Stoplight picture";
8: ImageMapStopLight.HotSpotMode = HotSpotMode.PostBack;
9: RectangleHotSpot redHotSpot = new RectangleHotSpot();
10: redHotSpot.Top = 0;
11: redHotSpot.Bottom = 40;
12: redHotSpot.Left = 0;
13: redHotSpot.Right = 40;
14: redHotSpot.PostBackValue = "RED";
15: ImageMapStopLight.HotSpots.Add(redHotSpot);
16: RectangleHotSpot yellowHotSpot = new RectangleHotSpot();
17: yellowHotSpot.Top = 41;
18: yellowHotSpot.Bottom = 80;
19: yellowHotSpot.Left = 0;
20: yellowHotSpot.Right = 40;
21: yellowHotSpot.PostBackValue = "YELLOW";
22: ImageMapStopLight.HotSpots.Add(yellowHotSpot);
23: RectangleHotSpot greenHotSpot = new RectangleHotSpot();
24: greenHotSpot.Top = 81;
25: greenHotSpot.Bottom = 120;
26: greenHotSpot.Left = 0;
27: greenHotSpot.Right = 40;
28: greenHotSpot.PostBackValue = "GREEN";
29: ImageMapStopLight.HotSpots.Add(greenHotSpot);
30: }
31: protected void ImageMapStopLight_Click(object sender, ImageMapEventArgs e)
32: {
33: Label1.Text = "You clicked the " + e.PostBackValue + " rectangle.";
34: }
35: }

Kontrolka Calendar
Nazwa kontrolki mówi sama za siebie :) Umożliwia ona wyświetlenie na stornie web kalendarza. Pozwala ona wybierać jedną datę lub serie dat. Nie trzeba chyba mówić jak bardzo przydatna jest taka kontrolka. Jeśli chodzi o sprawy techniczne to dziedziczy on bezpośrednio z WebControl a w kodzie źródłowym zapisujemy ją <asp:Calendar>. Jednak w konsekwencji na stornie jeśli podejrzymy kod źródłowy zauważymy, że jest to najzwyklejsza w świecie tabelka (<table>) z wbudowanym javascript.
Kontrolka ta ma multum właściwości i nawet mi przez myśl nie przeszło, żeby je tutaj opisywać…w TK są dwie strony :) Poza tym celem artykułów jest nakreślenie tematyki a nie tłumaczenie TK ;) Chciałbym mimo wszystko powiedzieć o jednej właściwości z którą na pewno się spotkamy używając kalendarza a mianowicie SelectionMode. Określa ona czy możemy zaznaczyć jedną date, kilka a może w ogóle. Do wyboru mamy:
Day- pozwala wybrać tylko jeden dzień
DayWeek – pozwala wybrać dzień lub cały tydzień
DayWeekMonth – pozwala wybrać dzień, tydzień a nawet cały miesiąc
None – nie pozwala wybrać żadnej daty.
Poniżej obrazek pokazuje wszystkie właściwości a co za tym idzie możliwości tak wydawało by się skromnej kontrolki:

Poniżej przykład kodu z TK z użyciem kontrolki kalendarza:
1: //C#
2: public partial class CalendarCSharp : System.Web.UI.Page
3: {
4: Hashtable _scheduleData;
5: protected void Page_Load(object sender, EventArgs e)
6: {
7: _scheduleData = GetSchedule();
8: Calendar1.Caption = "Personal Schedule";
9: Calendar1.FirstDayOfWeek = FirstDayOfWeek.Sunday;
10: Calendar1.NextPrevFormat = NextPrevFormat.ShortMonth;
11: Calendar1.TitleFormat = TitleFormat.MonthYear;
12: Calendar1.ShowGridLines = true;
13: Calendar1.DayStyle.HorizontalAlign = HorizontalAlign.Left;
14: Calendar1.DayStyle.VerticalAlign = VerticalAlign.Top;
15: Calendar1.DayStyle.Height = new Unit(75);
16: Calendar1.DayStyle.Width = new Unit(100);
17: Calendar1.OtherMonthDayStyle.BackColor = System.Drawing.Color.Cornsilk;
18: Calendar1.TodaysDate = new DateTime(2009, 2, 1);
19: Calendar1.VisibleDate = Calendar1.TodaysDate;
20: }
21: private Hashtable GetSchedule()
22: {
23: Hashtable schedule = new Hashtable();
24: schedule["2/9/2009"] = "Vacation Day";
25: schedule["2/18/2009"] = "Budget planning meeting @ 3:00pm";
26: schedule["2/24/2009"] = "Dinner plans with friends @ 7:00pm";
27: schedule["2/27/2009"] = "Travel Day";
28: schedule["3/5/2009"] = "Conf call @ 1:00pm";
29: schedule["3/10/2009"] = "Meet with art director for lunch";
30: schedule["3/27/2009"] = "Vacation Day";
31: return schedule;
32: }
33: protected void Calendar1_SelectionChanged(object sender, EventArgs e)
34: {
35: LabelAction.Text = "Selection changed to: "
36: + Calendar1.SelectedDate.ToShortDateString();
37: }
38: protected void Calendar1_VisibleMonthChanged(object sender,
39: MonthChangedEventArgs e)
40: {
41: LabelAction.Text = "Month changed to: " + e.NewDate.ToShortDateString();
42: }
43: protected void Calendar1_DayRender(object sender,
44: DayRenderEventArgs e)
45: {
46: if (_scheduleData[e.Day.Date.ToShortDateString()] != null)
47: {
48: Literal lit = new Literal();
49: lit.Text = "<br />";
50: e.Cell.Controls.Add(lit);
51: Label lbl = new Label();
52: lbl.Text = (string)_scheduleData[e.Day.Date.ToShortDateString()];
53: lbl.Font.Size = new FontUnit(FontSize.Small);
54: e.Cell.Controls.Add(lbl);
55: }
56: }
57: }
Kontrolka FileUpload
Kontrolka pozwala wysłać na serwer pojedynczy plik. Ścieżkę do pliku możemy wpisać ręcznie bądź wybrać ją z dysku klikając na przycisk Przeglądaj. Kontrolka ta dziedziczy z WebControl i na stornie jest dokładnie <input type="file">. Samo wybranie pliku nie wywołuje PostBacka, dopiero po wciśnięciu w przycisk wyślij (który sami musimy zdefiniować) plik zostaje umieszczony na serwerze. Możemy oczywiście ograniczyć rodzaj wysyłanych plików, jego wielkość itd. Dla przykładu maksymalny rozmiar pliku jest określony przez MaxRequestLength atrybutu httpRuntime w web.config.
Przykład kodu oraz zrzut ekranu zastosowania tej kontrolki, poniżej:
1: //C#
2: protected void Button1_Click(object sender, EventArgs e)
3: {
4: if (FileUpload1.HasFile)
5: {
6: Label1.Text = "File Length: "
7: + FileUpload1.FileBytes.Length
8: + "<br />"
9: + "File Name: "
10: + FileUpload1.FileName
11: + "<br />"
12: + "MIME Type: "
13: + FileUpload1.PostedFile.ContentType;
14: FileUpload1.SaveAs(
15: MapPath("~/Uploads/" + FileUpload1.FileName));
16: }
17: else
18: {
19: Label1.Text = "No file received.";
20: }
21: }

Kontrolka Panel
Kontrolka ta służy do grupowania innych kontrolek. Czasami potrzebujemy taki kontener kontrolek, który chcemy żeby był np. widoczny w pewnych okolicznościach dla użytkownika. Technicznie kontrolka ta dziedziczy z WebControl a w kodzie źródłowym jest to element <asp:Panel>. Ostatecznie jednak w przeglądarce otrzymujemy diva :)
Poniżej przykład kodu z Panelem. Po kliknięciu w przycisk zmienia się stan widoczności kontrolki:
1: <body>
2: <form id="form1" runat="server">
3: <div>
4: <asp:Button ID="ButtonShowHide" runat="server" Text="Login: hide form"
5: width="200" onclick="ButtonShowHide_Click"/>
6: <asp:Panel ID="Panel1" runat="server" BackColor="Beige" Width="200">
7: <asp:Label ID="Label1" runat="server" Text="User name: "></asp:Label>
8: <br />
9: <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
10: <br />
11: <asp:Label ID="Label2" runat="server" Text="Password: "></asp:Label>
12: <br />
13: <asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
14: <br />
15: <asp:Button ID="ButtonLogin" runat="server" Text="Login" />
16: </asp:Panel>
17: </div>
18: </form>
19: </body>
1: //C#
2: protected void ButtonShowHide_Click(object sender, EventArgs e)
3: {
4: Panel1.Visible = !Panel1.Visible;
5: if (Panel1.Visible)
6: {
7: ButtonShowHide.Text = "Login: hide form";
8: }
9: else
10: {
11: ButtonShowHide.Text = "Login: show form";
12: }
13: }
Kontrolki Multiview i View
Tak jak Panel kontrolka MultiView służy do grupowania kontrolek. Kontrolki View muszą znajdować się w Multiview. Poszczególne widoki możemy ukrywać kiedy korzystamy z innego co umożliwia nam np. zrobienie kreatora. Kontrolka ta dziedziczy z klasy Control w kodzie źródłowym jest reprezentowana jako <asp:MultiView> a View który musi być wewnątrz jako <asp:View>. W przeglądarce nie jest generowany jakiś specjalny odpowiednik html.
Przykładowy kod wykorzystania kontrolek, strony z widokiem do niej oraz przykład ogólny strony gdzie możemy wykorzystać te kontrolki poniżej:

1: //C#
2: public partial class ViewControl : System.Web.UI.Page
3: {
4: protected void Page_Load(object sender, EventArgs e)
5: {
6: MultiView1.ActiveViewIndex = 0;
7: }
8: protected void Button_Command(object sender, CommandEventArgs e)
9: {
10: switch (e.CommandName)
11: {
12: case "Step1Next":
13: MultiView1.ActiveViewIndex = 1;
14: break;
15: case "Step2Back":
16: MultiView1.ActiveViewIndex = 0;
17: break;
18: case "Step2Next":
19: MultiView1.ActiveViewIndex = 2;
20: break;
21: case "Step3Back":
22: MultiView1.ActiveViewIndex = 1;
23: break;
24: case "Finish":
25: //hide control from user to simulate save
26: MultiView1.ActiveViewIndex = -1;
27: break;
28: }
29: }
30: }

Kontrolka Wizard
Jest to w pewnym stopniu odpowiednik kontrolki MultiView. Pozwala ona na stworzenie kreatora gdzie możemy w pewien logiczny sposób podzielić pewne fragmenty informacji, a na koniec zapisać wynik naszej pracy. Są wbudowane określenia które determinują jakie przyciski mają być widoczne na poszczególnym kroku.
WizardStepType.Auto – jest to domyślne ustawienie które generują przycisk w oparciu o lokalizacje w kolekcji
WizardStepType.Complete – jest to ostatni krok do wyświetlenia nie generujący przycisków
WizardStepType.Finish – generuje przycisk Finish i Previous
WizardStepType.Start – jest to wyjściowy krok i generuje przycisk Next
WizardStepType.Step – generuje przyciski Next i Previous
Przykład kodu i wyglądu poszczególnych kroków poniżej:

1: //C#
2: public partial class WizardCSharp : System.Web.UI.Page
3: {
4: protected void Page_Load(object sender, EventArgs e)
5: {
6: if (!IsPostBack)
7: {
8: Wizard1.ActiveStepIndex = 0;
9: }
10: }
11: protected void Wizard1_FinishButtonClick(object sender,
12: WizardNavigationEventArgs e)
13: {
14: Wizard1.Visible = false;
15: Response.Write("Finished<br />" + Label1.Text);
16: }
17: protected void Wizard1_NextButtonClick(object sender,
18: WizardNavigationEventArgs e)
19: {
20: if (Wizard1.WizardSteps[e.NextStepIndex].Title == "Summary")
21: {
22: Label1.Text = String.Empty;
23: foreach (WizardStep ws in Wizard1.WizardSteps)
24: {
25: foreach (Control c in ws.Controls)
26: {
27: if (c is CheckBox)
28: {
29: CheckBox cb = (CheckBox)c;
30: if (cb.Checked)
31: {
32: Label1.Text += cb.Text + "<br />";
33: }
34: }
35: }
36: }
37: }
38: }
39: }
Kontrolka Xml
Kontrolka ta jest wykorzystywana do wyświetlania danych które mamy zapisane w formacie XML. Szczególnie jest przydatna kiedy chcemy dokonać transformacji na Extensible Stylesheet Language (XSL).
Przykłady poniżej pokazują jak wygląda XML, wygenerowany XSL i jak to prosto zrealizować w kodzie:
1: <?xml version="1.0" encoding="utf-8" ?>
2: <ProductList>
3: <Product Id="1A59B" Department="Sporting Goods" Name="Baseball" Price="3.00" />
4: <Product Id="9B25T" Department="Sporting Goods" Name="Tennis Racket" Price="40.00" />
5: <Product Id="3H13R" Department="Sporting Goods" Name="Golf Clubs" Price="179.00" />
6: <Product Id="7D67A" Department="Clothing" Name="Shirt" Price="12.00" />
7: <Product Id="4T21N" Department="Clothing" Name="Jacket" Price="45.00" />
8: </ProductList>
1: <?xml version="1.0" encoding="utf-8" ?>
2: <xsl:stylesheet version="1.0"
3: xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
4: xmlns:msxsl="urn:schemas-microsoft-com:xslt"
5: xmlns:labs="http://labs.com/mynamespace">
6: <xsl:template match="/">
7: <html>
8: <head>
9: <title>Product List</title>
10: </head>
11: <body>
12: <center>
13: <h1>Product List</h1>
14: <xsl:call-template name="CreateHeading"/>
15: </center>
16: </body>
17: </html>
18: </xsl:template>
19: <xsl:template name="CreateHeading">
20: <table border="1" cellpadding="5">
21: <tr >
22: <th bgcolor="yellow">
23: <font size="4" >
24: <b>Id</b>
25: </font>
26: </th>
27: <th bgcolor="yellow">
28: <font size="4" >
29: <b>Department</b>
30: </font>
31: </th>
32: <th bgcolor="yellow">
33: <font size="4" >
34: <b>Name</b>
35: </font>
36: </th>
37: <th bgcolor="yellow">
38: <font size="4" >
39: <b>Price</b>
40: </font>
41: </th>
42: </tr>
43: <xsl:call-template name="CreateTable"/>
44: </table>
45: </xsl:template>
46: <xsl:template name="CreateTable">
47: <xsl:for-each select="/ProductList/Product">
48: <tr>
49: <td align="center">
50: <xsl:value-of select="@Id"/>
51: </td>
52: <td align="center">
53: <xsl:value-of select="@Department"/>
54: </td>
55: <td>
56: <xsl:value-of select="@Name"/>
57: </td>
58: <td align="right">
59: <xsl:value-of select="format-number(@Price,'$#,##0.00')"/>
60: </td>
61: </tr>
62: </xsl:for-each>
63: </xsl:template>
64: </xsl:stylesheet>
1: //C#
2: public partial class XmlControlVb : System.Web.UI.Page
3: {
4: protected void Page_Load(object sender, EventArgs e)
5: {
6: Xml1.DocumentSource = "App_Data/ProductList.xml";
7: Xml1.TransformSource = "App_Data/ProductList.xsl";
8: }
9: }

Dzięki za uwagę, do poniedziałku!!!