Die Kalender-Komponente in ASP.NET
Geschrieben von: Christian Holm Im Moment nicht allzu oft angetroffen, aber dennoch sehr nützlich - ein Kalender auf der Webseite. Vielleicht aufgrund der Tatsache, daß in HTML oder ASP dies sehr aufwendig war und ist. Das ändert sich nun mit der Calendar-Komponente von ASP.NET. Mit ein paar Handgriffen zaubern Sie einen Kalender der nicht nur hübsch ausschaut, sondern auch funktionell ist - das ist Rapid Development! Voraussetzung um den Sourcecode dieses Artikels verwenden zu können ist eine Installation des Microsoft .NET Framework SDK's auf einem Webserver. Weiters setze ich voraus, daß der Leser die Programmiersprache C# zu einem gewissen Grad beherrscht - es finden sich etliche Artikel auf diesem Server, um das notwendige Wissen zu erlernen. Wozu?Das werden Sie sich vielleicht schon nach den paar Zeilen fragen; Nützlich macht sich diese ASP.NET Web Form Control nicht einfach nur als graphisch aufgepeppter Webkalender, sondern auch für News Seiten, in der man die aktuellen Headlines lesen, oder auch im "News-Archiv" stöbern kann - oder für einfache Reservierungsaufgaben (Bestellungen, Tickets). Mit etwas mehr Geschick programmieren Sie sich webbasierende To-Do-Listen, oder Spickzettel welche Sie an speziellen Tagen an wichtige Aufgaben erinnern. Sie vergessen Weihnachten nicht mehr, oder "basteln" einen kleinen, aber feinen Terminplaner. Das Angenehme an der Komponente ist, daß sie einfach zu programmieren ist und reich an Funktionen ist und man sie modular aufbauen kann, d.h. sie ist einfach wiederzuverwenden. Getting StartedDie Calendar-Komponente bietet einen Monatskalender mit dem der Client einzelne Tage, ganze Wochen oder Monate auswählen kann. Die Navigation gestaltet sich einfachst, indem man entweder an die Pfeile in der Titelleiste oder je nach Einstellung auf den Monatsnamen klickt. Die Calender Web Control integriert mit dem Microsoft .Net Framework DateTime Objekt, d.h. Sie erhalten kompletten Datum-Support für das Format des darzustellenden Datumsstrings, was auch für den Gültigkeitsbereich gilt. Es können also Datumswerte von 0 bis 9999(!) n. Chr. ausgeben werden - also lassen sich auch Ihre Zukunftspläne oder die Geburtstage Ihrer Ur-Ur-Enkel vermerken. Beachte: Die Calendar-Control wird beim Client als HTML-Table gerendert, wenn die ASP.NET Web Forms Seite - Sie erinnern sich <forms> ... </forms> - am Web Server geparsed wird. Das bedeutet, daß einige Eigenschaften der Komponente, welche sich auf die Table-Formatierung beziehen, zu Fehlern in der Darstellung bei manchen (älteren) Browsern führen können. Um den Client vor etwaigen Fehlermeldungen zu bewahren, verwendet man die @ Page-Directive <%@ Page ClientTarget="DownLevel" %>. Damit wird kompatibelstes HTML ausgegeben. Kommunikationen mit einer Datenbank (Data Binding) ist nicht "direkt" mit der Calendar-Komponente möglich. Verständlich, da man ja den gesamten Kalender in die Datenbank einbinden müsste und das bei dem Gültigkeitsbereich! Hier schafft man sich Abhilfe mit einem Handler der das OnDayRender Event implementiert. Dieser greift sich dann nur die jeweils benötige Info aus der Datenbank und fügt diese dann in den Browserstream der zum Client gesendet wird. Aber beginnen wir vorerst mit einfachen Beispielen, um Sie erstmal mit dieser Komponente vertraut zu machen. Im aller einfachsten Fall ist für einen einfachen Webkalender nur dies zu programmieren (calendar.aspx): <%@ Page Language="C#" Culture="de-AT"%> <html> <body> <h2>ASP.NET Calendar Web Control</h2> <form runat="server"> <asp:Calendar id=Kalender1 runat="server" /> </form> </body> </html> So sieht das dann im Browser aus: Zugegeben, das Resultat ist nicht besonders berauschend, aber dennoch funktionell. Beachte: Die Darstellung der Tagesnamen ist von den Ländereinstellungen Ihres Servers abhängig. Wenn Sie also ein Produkt der Microsoft Windows 2000 Server Family in Deutsch besitzen, ist die Directiven- Angabe <%@ Culture="de-AT"%> überflüssig. Auf unseren US System hingegen würden wir ohne diese Anweisung englische Tagesnamen erhalten. Da wir eine ASP.NET Web Control verwenden, müssen wir auch die Komponente mit <form> ... </form> umschließen und mit runat="server" ermöglichen wir eine serverseitige Abarbeitung. Das Kernstück der Komponente ist natürlich <asp:Calendar id=Kalender1 runat="server" />. Was hier in nur diesem Beispiel nicht unbedingt nötig ist, ist die Vergabe der ID. Diese ID muß für jede Web Control eindeutig sein, damit Interaktionen zwischen den einzelnen Controls möglich sind. Beispiel für eine solche Interaktion wäre, daß der Inhalt einer TextBox mittels eines RequiredFieldValidator überprüft wird. Einige Eigenschaften der Control tun auch was fürs Auge; aus dem Standard-Look wird schnell ein optisch ansehnliches Werkzeug. Die gesamte Komponente läßt sich durchstylen, angefangen von der Ausschreibung der Monatsnamen über Titelleistenfarbe bis zur Zellengröße - also Farbe, Form, Größe, Navigation und Steuerung von Events. Jedem sein Geschmack, aber man sollte es auch nicht übertreiben, deshalb ist die Control im nächsten Screenshot nur im Rahmen des Erträglichen optisch verändert worden. Dieser Screenshot enthält aber auch schon zusätzliche nicht-graphische Funktionalitäten, die ich nun in den folgenden Beispielen erklären möchte. Format-OptionenIn diesem Beispiel geht es nicht darum, die Calendar-Control bunt und poppig zu machen, sondern einfach die Beschriftung dem persönlichen Geschmack anzupassen. Das Beispiel ist bereits so angelegt, daß der Client durch einfache ASP.NET Web Control Steuerung diese Entscheidungen treffen kann. Natürlich kann man dasselbe Spielchen auch für die Farben des Kalenders, für die Rahmenformatierung etc. treiben. Aber: Da ich mir die Arbeit ersparen wollte, alle 16,7 Millonen Hex-Farbwerte in eine DropDownList-Control einzutragen, habe ich die Kriterien genommen, die auch wichtig sind und weniger Elemente besitzten. Außerdem für die Farbwerte funktionierts ja prinzipiell analog (cal_Format.aspx): <%@ Page Language="C#" Culture="de"%> <html> <body> <script language="C#" runat="server"> void Page_Load(Object Src, EventArgs E) { if (!Page.IsPostBack) { DNFormAuswahl.Items.Add(new ListItem("Ein Buchstabe",Enum.Format(typeof(DayNameFormat),_ DayNameFormat.FirstLetter,"D"))); DNFormAuswahl.Items.Add(new ListItem("Zwei Buchstaben",Enum.Format(typeof(DayNameFormat),_ DayNameFormat.FirstTwoLetters,"D"))); DNFormAuswahl.Items.Add(new ListItem("Volle Bezeichung",Enum.Format(typeof(DayNameFormat),_ DayNameFormat.Full,"D"))); DNFormAuswahl.Items.Add(new ListItem("Kurzbezeichung",Enum.Format(typeof(DayNameFormat),_ DayNameFormat.Short,"D"))); NPFormAuswahl.Items.Add(new ListItem("Monat kurz",Enum.Format(typeof(NextPrevFormat),_ NextPrevFormat.ShortMonth,"D"))); NPFormAuswahl.Items.Add(new ListItem("Monat lang",Enum.Format(typeof(NextPrevFormat),_ NextPrevFormat.FullMonth,"D"))); TFormAuswahl.Items.Add(new ListItem("Monat/Jahr",Enum.Format(typeof(TitleFormat),_ TitleFormat.MonthYear,"D"))); TFormAuswahl.Items.Add(new ListItem("Monat",Enum.Format(typeof(TitleFormat),_ TitleFormat.Month,"D"))); } } ... In diesem Sourcecode-Block wird, wie immer zuerst die Seitensprache (hier C#) festgelegt. Dann lasse ich mir für das Pulldown-Menü die Listeneinträge vorgenerieren, wobei Page.IsPostBack überprüft ob die Seite durch einen Client postback geladen wird. Hier soll dies zuerst nicht der Fall sein, daher auch ! davor gestellt. Es folgt - das Ende des Scriptblockes: ... void ChangedDisplay(Object sender, EventArgs e) { int nDayNameFormat = Convert.ToInt32(DNFormAuswahl.SelectedItem.Value); Kalender1.DayNameFormat = (DayNameFormat)nDayNameFormat; int nNextPrevFormat = Convert.ToInt32(NPFormAuswahl.SelectedItem.Value); Kalender1.NextPrevFormat = (NextPrevFormat)nNextPrevFormat; int nTitleFormat = Convert.ToInt32(TFormAuswahl.SelectedItem.Value); Kalender1.TitleFormat = (TitleFormat)nTitleFormat; } </script> ... Der Delegate ChangedDisplay wird ausgeführt, wenn eine Auswahl im Pulldown-Menü getroffen wird. Dann wird der, in diesem Anweisungsblock enthaltene Code ausgeführt, d.h. die Attribute für die Calendar-Control werden je nach (Client-) Auswahl gesetzt. ... <h2>ASP.NET Calendar Web Control</h2> <form runat="server"> <p> <b>Formatoptionen:</b></p> <table> <tr> <td>Bezeichnung der Tage im Kalender:</td> <td><asp:dropdownlist id="DNFormAuswahl" runat="server" AutoPostBack="True" OnSelectedIndexChanged="ChangedDisplay" /></td> </tr> <tr> <td>Formatierung des Monatsnamens für die Navigation: </td> <td><asp:dropdownlist id="NPFormAuswahl" runat="server" AutoPostBack="True" OnSelectedIndexChanged="ChangedDisplay" /></td> </tr> <tr> <td>Formatierung des Statusbalkens:</td> <td><asp:dropdownlist id="TFormAuswahl" runat="server" AutoPostBack="True" OnSelectedIndexChanged="ChangedDisplay" /></td> </tr> </table> <asp:Calendar id=Kalender1 Runat="server" DayNameFormat="FirstTwoLetters" NextPrevFormat="FullMonth" TitleFormat="Month" BorderWidth="1" ShowGridLines="True" CellPadding="3" CellSpacing="0" TitleStyle-BackColor="#aaaadd" TitleStyle-BorderColor="black" TitleStyle-BorderWidth="1" SelectedDayStyle-BackColor="orange" /> </form> </body> </html> Zunächst werden die DropDownList-Controls erstellt. Diese beinhalten die Formatoptionen, mit denen wir das Aussehen der Calendar-Control verändern möchten. Hier beweist sich wieder einmal, wie wichtig die Vergabe von einzelnen IDs ist. Die Änderungen im Index der DropDownList-Control wird ja durch die Anweisungen im Delegate ChangeDisplay (siehe oben) erst bewirkt. Die erste DropDownList-Control definiert wie die Wochentage anzeigt werden (DayNameFormat), also z.B. für Montag entweder "M" (FirstLetter), "Mo" (FirstTwoLetters), oder "Montag" (Full). Die Kurzbezeichnung (Short) ähnelt der Methode FirstTwoLetters. Das Attribut NextPrevFormat definiert die Art wie der Navigationslink zwischen den Monaten erfolgen soll, also eine kurze Bezeichnung, z.B. für Juli "Jul" oder die lange Version "Juli". Damit im Statusbalken nur der Monat dargestellt wird setzt man das Attribut TitleFormat auf "Month", andernfalls, wenn zusätzlich auch noch das dazugehörige Jahr angezeigt werden soll, dann erfolgt die Zuweisung TitleFormat="MonthYear". Beachte: Damit man die Attribute der Calendar Control dann auch verwenden kann, muß dann letztendlich eine Umcastung auf Int32 erfolgen, da die Control nur mit numerischen Argumenten arbeiten kann. Bei der Calendar-Web Control ist zu beachten, daß ihr eine eindeutige ID zugewiesen wird (id=Kalender1) und daß das Runat="server"-Attribut gesetzt ist. Der Rest der Attribute dienen dem optischen Glanz und sind eigentlich selbsterklärend. Die SelectionMode EigenschaftStandardmäßig kann man nur einen Tag im Kalender auswählen, was oft zuwenig ist. Mit der SelectionMode Eigenschaft kann man also nicht nur einen Tag auswählen, sondern eine ganze Woche oder auch einen Monat. Dies wird durch das Attribut SelectionMode="DayWeek" innerhalb der Control ermöglicht. Diese Attributoption ermöglicht eine zusätzliche Auswahl einer Woche. Ab dem Zeitpunkt der Verwendung der Attributoption "DayWeek" erhalten Sie in der Darstellung der Control im Browser links neben der Control eine zusätzliche Navigationsleiste, die das Anwählen erleichtert; das gleiche gilt dann auch für Attributoption "DayWeekMonth", wo Sie dann auch Monate auswählen können. Es erscheint im Browser die Möglichkeit ein gesamtes Monat auszuwählen. Im folgenden Beispiel ist diese Funktion mit Hilfe eines Pulldown-Menüs (asp:dropdownlist) realisiert. Das Pulldown-Menü soll hier das Ausprobieren der Attribute vereinfachen und später dem Client u. a. ermöglichen den Kalender zu personalisieren - dies ist einfach möglich da bei Web Controls der Viewstate automatisch zwischen den Requests erhalten bleibt. Da das nächste Beispiel schon umfangreicher ist als das vorige, gehe ich die Anweisungsblöcke getrennt durch (cal_SelMode.aspx). <%@ Page Language="C#" Culture="de"%> <html> <body> <script language="C#" runat="server"> void Page_Load(Object Src, EventArgs E) { if (!Page.IsPostBack) { SelMode.Items.Add(new ListItem("Keine Auswahl",Enum.Format(typeof(CalendarSelectionMode), _ CalendarSelectionMode.None,"D"))); SelMode.Items.Add(new ListItem("Tag-Auswahl",Enum.Format(typeof(CalendarSelectionMode), _ CalendarSelectionMode.Day,"D"))); SelMode.Items.Add(new ListItem("Tag/Woche-Auswahl",Enum.Format(typeof(CalendarSelectionMode), _ CalendarSelectionMode.DayWeek,"D"))); SelMode.Items.Add(new ListItem("Tag/Woche/Monat-Auswahl",Enum.Format(typeof(CalendarSelectionMode), _ CalendarSelectionMode.DayWeekMonth,"D"))); } } ... Wie im vorigen Beispiel wird die Seitensprache definiert, die Art des Requests überprüft (erster, folgende) und die Listeneinträge vorgeneriert - The same procedure as last time! Als nächstes: ... void ChangedDisplay(Object sender, EventArgs e) { int nValue = Convert.ToInt32(SelMode.SelectedItem.Value); Kalender1.SelectionMode = (CalendarSelectionMode)nValue; } void Date_Selected(object s, EventArgs e) { CurDate.Text = "Ausgewähltes Datum: " + Kalender1.SelectedDate.ToShortDateString(); } </script> ... Der Delegate ChangedDisplay tritt dann in Aktion, wenn eine Auswahl im Pulldown-Menü getroffen wird. Dann wird der im Anweisungsblock enthaltene Code ausgeführt. In diesem Fall wird dem Attribut SelectionMode ein neuer Wert zugewiesen, der die Auswahloptionen (Tag/Monat/Jahr) im Kalender verändert. Zusätzlich gibt es ein kleines Zusatzfeature im Delegate Date_Selected, das das ausgewählte Datum unter dem Kalender in Form eines Label-Controls bestätigt. ToShortDateString() ist deshalb nötig weil die Label-Control nur Daten als Strings übernehmen kann. Dies ist auch schon das Ende des Script-Blockes; nun folgen die Erstellung der DropDownList Web Control und die Generierung der Calendar-Komponente. ... <h2>ASP.NET Calendar Web Control</h2> <form runat="server"> <table> <tr> <td>Auswahloptionen für Anzeige: </td> <td><asp:dropdownlist id="SelMode" runat="server" AutoPostBack="True" OnSelectedIndexChanged="ChangedDisplay"/></td> </tr> </table> <p> </p> <asp:Calendar id=Kalender1 Runat="server" onselectionchanged="Date_Selected" SelectionMode="DayWeekMonth" DayNameFormat="FirstTwoLetters" NextPrevFormat="FullMonth" TitleFormat="MonthYear" BorderWidth="1" ShowGridLines="True" CellPadding="3" CellSpacing="0" TitleStyle-BackColor="#aaaadd" TitleStyle-BorderColor="black" TitleStyle-BorderWidth="1" SelectWeekText = "Woche" SelectMonthText = "Monat" SelectedDayStyle-BackColor="orange" SelectedDayStyle-Font-Bold="True" /> <asp:Label id=CurDate runat="server" /> </form> </body> </html> Der DropDownList-Control ist eine ID zugewiesen, mit der wir am Anfang des Sourcecodes die Listeneinträge generiert haben. Die Web Control wird durch einen Client PostBack gesteuert. Wenn eine Auswahl in der Control stattfindet, dann wird der Delegate ChangedDisplay - wie oben beschrieben - ausgeführt. Als nächstes folgt die Calendar-Komponente. Abgesehen von den Kalender-Formatoptionen soll, wenn ein Datum ausgewählt wurde, der Delegate Date_Selected (Eintrag: OnSelectionChanged=) ausgeführt werden, welcher in Verbindung mit der weiter unten befindlichen Label-Control das Datum bestätigt. SelectionMode beinhaltet die Möglichkeit, wie schon beschrieben, Tage/Wochen/Monate auszuwählen. DayNameFormat bewirkt, daß die Wochentage mit zwei Buchstaben angegeben werden. Bei dieser Calendar Control erfolgt die Navigation zwischen den Monaten so, daß der Verweis mit dem vollen Monatsnamen angegeben ist (NextPrevFormat="FullMonth"). Im Titelbalken wird der aktuelle Monat samt dazugehörigem Jahr angegeben (TitleFormat="MonthYear"). Den Auswahl-Linktext, der dann in der zusätzlichen Navigationsleiste aufscheint, können Sie für die Angabe einer "ganzen Woche" mit SelectWeekText definieren; analog hier zu den für die Monatsauswahl (SelectMonthText). Die SelectRange MethodeDie zuvor beschriebene SelectMode-Methode läßt aber unter Umständen einige Wünsche offen; z.B. ist es nicht immer erwünscht die Auswahl auf die gesamte Woche oder den gesamten Monat zu beschränken. Mit der SelectRange-Methode können Sie individuelle Start- und Endwerte für den Auswahlbereich festlegen. Die Einbindung geschieht wie folgt (cal_SelRange.aspx): <%@ Page ClientTarget="DownLevel" Culture="de"%> <html> <body> <script language="C#" runat=server> void btnSubM_Click(Object sender, EventArgs e) { if (Page.IsPostBack && Page.IsValid) { DateTime dt1 = Convert.ToDateTime(txtdt1.Text); DateTime dt2 = Convert.ToDateTime(txtdt2.Text); Kalender1.SelectedDates.SelectRange(dt1, dt2); } } </script> ... Der Aufruf des Scriptblockes erfolgt durch Anklicken des "Bereich auswählen"-Buttons (im Sourcecode "btnSubM" benannt). Im Anweisungsblock wird die Seite zuerst auf IsPostBack und IsValid (dazu später mehr) geprüft. Damit ich die SelectRange-Methode auf die Calendar-Control anwenden kann, muß ich zuerst die beiden Datumsgrenzen "Von" Datum (dt1) und "Bis" Datum (dt2) als Variablen des Datentyps DateTime deklarieren. Zusätzlich erfolgt im gleichen Schritt die Wertzuweisung aus den beiden TextBox Web Controls, mit deren Eingaben der Client den Datumsbereich festlegt. Danach erfolgt die Wertübergabe zu der Calendar-Control (Kalender1.SelectedDates.SelectRange(dt1, dt2);). Als Gustostückerl habe ich mir erlaubt, die Eingabe des Clients auf korrekte Datumseingabe (mm/tt/jjjj) zu überprüfen. Dies habe ich mit dem CompareValidator gelöst - einfach aber nützlich. Damit verhindere ich, daß der Client für die Datumseingabe andere (z.B. nicht numerische) Formate als das vorgegebene (mm/tt/jjjj) eingeben kann und vermeide schon das erste Bombardement durch Exceptions. Was hier allerdings nicht überprüft wird ist, ob der User sich an die Eingabereihenfolge gehalten hat. Also zuerst der Monat, dann Tag (und zum Schluß das vierstellige Jahr). Eine zweistellige Eingabe des Jahres ist aber auch "gefahrlos" möglich. Sehen wir uns den CompareValidator etwas genauer an: ... <td>Von (tt/mm/jjjj): </td> <td><asp:textbox id="txtdt1" runat="server"/></td> <td><asp:CompareValidator id="ChkDte1" Type="Date" ControlToValidate="txtdt1" operator="DataTypeCheck" valueToCompare="01/01/2000" errorMessage="<b>Von:</b> Ungültiges Datum" runat="server"/> </td> ... Die TextBox-Web Control übernimmt den Bereichsanfangswert des Clients. Dies geschieht bei <asp:textbox id="txtdt1" runat="server"/>. Der Eingabewert wird nun mittels CompareValidator auf den richtigen Datentyp hin überprüft. Die Festlegung des zu vergleichenden Datentyps erfolgt mit Type="DateTime". Das operator-Attribut dient dazu, dem Validator vorzugeben welchen Vergleich er machen soll. In unserem Fall ist operator="DataTypeCheck", also vergleichen des Datentyps "DateTime" mit dem der Cienteingabe. Bei dem Attribut errorMessage können Sie eine benutzerdefinierte Fehlermeldung bzw. Hinweis ausgeben, wenn der Vergleich fehlgeschlagen ist. Zwar ist diese Überprüfung noch nicht vollständig "deppensicher", aber für unser Beispiel mehr als ausreichend. Das Resultat des Scripts zeigt der abschließende Screenshot: SchlußbemerkungIn diesem Artikel haben Sie die Grundfertigkeiten erlernt, auf Ihren ASP.NET Webseiten die Calendar Web Control sinnvoll einzubauen. Sie sind in der Lage, die Control Ihrem oder dem Geschmack des Users anzupassen und Datumsauswahlen zu tätigen - und das einfach und ohne viel Sourcecode! Was ich Ihnen aber bis jetzt verschwiegen habe, ist wie man aus der simplen Web Control einen leistungsfähigen Terminplaner bzw. To-Do-Listen macht. Dieses Thema werde ich natürlich in einem der folgenden ASPHeute-Artikel behandeln! Bevor wir dieses Thema jedoch behandeln sind aber die Grundlagen des Datenbankzugriffs in ASP.NET bzw. mit ADO+ und der Control Validation nötig. Download des CodesKlicken Sie hier, um den Download zu starten. Verwandte Artikel
Einführung in ASP.NET Web Forms Wenn Sie jetzt Fragen haben...Wenn Sie Fragen rund um die in diesem Artikel vorgestellte Technologie haben, dann schauen Sie einfach bei uns in den Community Foren der deutschen .NET Community vorbei. Die Teilnehmer helfen Ihnen gerne, wenn Sie sich zur im Artikel vorgestellten Technologie weiterbilden möchten. Eine weitere sehr hilfreiche Resource ist das deutsche ASP.NET Wiki, das als zentrale Anlaufstelle für Tips, Tricks, Know How und alles Nützliche was man in seinem Alltag als (ASP).NET-Entwickler so braucht und entdeckt gedacht ist. Haben Sie Fragen die sich direkt auf den Inhalt des Artikels beziehen, dann schreiben Sie dem Autor! Unsere Autoren freuen sich über Feedback zu ihren Artikeln. Ein einfacher Klick auf die Autor kontaktieren Schaltfläche (weiter unten) und schon haben Sie ein für diesen Artikel personalisiertes Anfrageformular.
Und zu guter Letzt möchten wir Sie bitten, den Artikel zu bewerten. Damit helfen Sie uns, die Qualität der Artikel zu verbessern - und anderen Lesern bei der Auswahl der Artikel, die sie lesen sollten.
©2000-2006 AspHeute.com |