DataPicker W aplikacjach web uzyskujesz różne informacje od użytkowników za pomocą textboxów i checkboxów. Często jednak musisz uzyskać informacje kalendarzowe od użytkowników, np. użytkownik w filtrowaniu rekordów danych w aplikacji web może użyć dat.

 

Jednak jak te dane uzyskać od użytkownika. Sprawa wydaje się prosta, wystarczy dać użytkownikowi textbox i dołączyć do niego jakąś prostą walidację. Tak, coś w tym stylu.

image

Problem jednak leży po stronie użytkownika i doświadczaniu aplikacji. Nie możemy wymagać od użytkownika podania daty z palca oraz oczekiwania , że zgadnie poprawny format daty[dd-MM-yyyy] jaki ustaliliśmy na stronie.

Dlatego w takich przypadkach powinna pojawić się kontrolka "DatePicker" , która wyświetla kalendarz, na którym użytkownik może klikać i wybierać daty.

Nie ma jednego dobrego sposobu implementacji wybieracza daty w ASP.NET. Dlatego przedstawię aż trzy sposoby rozwiązania tego problemu . Każdy z nich ma jakąś zaletę i wadę.

Oto te trzy rozwiązania:

  • Własny kod i kontrolka Calendar z ASP.NET
  • Kontrolka DatePicker z Ajax Control Toolkit
  • Użycie pluginu jQuery "DatePicker"

Teraz czas na prezentacje tych rozwiązań.

1. Kontrolka Calendar i własny kod

Kontrolka ASP.NET jest ogólnie dostępną kontrolką w frameworku. Co znaczy ,że nie trzeba instalować żadnych dodatkowych bibliotek i dodawać referencji, by z niej skorzystać.

Calendar Control


Wadą tej kontrolki jest fakt ,że jest to tylko kalendarz. Nie jest to gotowe okno dialogowe JavaScript , które się wyświetli, jak chcemy. Dlatego ta kontrolka nazywa się „Calendar” ,a nie "DatePicker".

Do tego rozwiązania będziemy musieli sami napisać kod, który będzie wywoływał to okno dialogowe.

Na początek zobaczmy jak wygląda strona z tym przykładem.

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Daty przy uzyciu własnego kodu i kontrolek ASP.NET</title>
    <script language="javascript" type="text/javascript">
        function PopupDatePicker(ctl) {
            var PopupWindow = null;
            PopupWindow = window.open('MyCustomDatePicker.aspx?ctl=' + ctl, '', 'width=250,height=250');
            PopupWindow.focus();
        }
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <asp:textbox ID="txtDate" runat="server"/>
    <asp:image runat="server" style="cursor:hand;" onclick="PopupDatePicker('txtDate')" 
        ImageUrl="~/image/calendar-extender-icon.png" />
    </form>
</body>
</html>

Na stronie znajduję się prosty textbox oraz obrazek. Musi to być obrazek, ponieważ domyślnie kliknięcie kontrolkę button, bądź imagebutton spowoduje automatyczne przeładowanie strony, a my tego nie chcemy.

Kliknięcie obrazka spowoduje uruchomienie okna dialogowego, które tak naprawdę jest inną stroną ASP.NET. Do okna dialogowego przekazujemy informacje o danej kontrolce textbox w URL. Dzięki temu ta funkcja może być użyta wielokrotnie dla wielu textbox-ów.

Oczywiście przykład nie kończy się tutaj, ponieważ nie mamy jeszcze strony „'MyCustomDatePicker.aspx”, która ma być wywoływana w funkcji JavaScript.

Do strony „'MyCustomDatePicker.aspx”dodajemy kontrolkę „Calendar”. Za pomocą magii Visual Studio możemy wystylizować kontrolkę za pomocą paru kliknięć.

stylizacja controlki Calendar
Do strony trzeba też dodać funkcje JavaScript, która przekaże wybraną datę do textboxa-a, który został podany wcześniej.

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>MyCustomDatePicker</title>
    <script type="text/javascript">
        function SetDate(dateValue, ctl) {

            thisForm = window.opener.document.forms[0].elements[ctl].value = dateValue;

            self.close();

        }
    </script>
</head>
<body>
    <form id="form1" runat="server">
<div>
    <asp:Calendar ID="CalendarControl" runat="server" BackColor="#FFFFCC" 
        BorderColor="#FFCC66" BorderWidth="1px" DayNameFormat="Shortest" 
        Font-Names="Verdana" Font-Size="8pt" ForeColor="#663399" Height="200px" 
        ondayrender="CalendarControl_DayRender" ShowGridLines="True" Width="220px">
        <DayHeaderStyle BackColor="#FFCC66" Font-Bold="True" Height="1px" />
        <NextPrevStyle Font-Size="9pt" ForeColor="#FFFFCC" />
        <OtherMonthDayStyle ForeColor="#CC9966" />
        <SelectedDayStyle BackColor="#CCCCFF" Font-Bold="True" />
        <SelectorStyle BackColor="#FFCC66" />
        <TitleStyle BackColor="#990000" Font-Bold="True" Font-Size="9pt" 
            ForeColor="#FFFFCC" />
        <TodayDayStyle BackColor="#FFCC66" ForeColor="White" />
    </asp:Calendar>
</div>
</form>
</body>
</html>
Jeśli się przyjrzysz temu kodowi zauważysz , że sama kontrolka nie wywołuje tej funkcji. Chcemy, aby każde pojedyncze kliknięcie na datę wewnątrz kalendarza zatwierdzało wybór użytkownika. Nie chcemy żadnych dodatkowych przycisków. Aby dodać do każdego przycisku dat hiperlinka z tą funkcją, musimy skorzystać z kodu pobocznego w C#.

image

Do kontrolki Calendar dodajemy zdarzenie „DayRender” , które zachodzi przy każdym rysowaniu daty wewnątrz kalendarza. Do tego zdarzenia dodajemy następujący kod.
 
protected void CalendarControl_DayRender(object sender, DayRenderEventArgs e)
{
    string ctrl = Request.QueryString["ctl"];
    HyperLink hpl = new HyperLink();
    hpl.Text = ((LiteralControl)e.Cell.Controls[0]).Text;
    hpl.NavigateUrl = "javascript:SetDate('" + e.Day.Date.ToShortDateString() + "','" + ctrl + "');";
    e.Cell.Controls.Clear();
    e.Cell.Controls.Add(hpl);
}

Domyślnie wszystkie wygenerowane daty przez kontrolkę calendar wywołują postback do serwera. Tutaj zamiast postback mamy wywołanie funkcji JavaScript „SetDate(). Jak to zostało wykonane.

Najpierw wyczyściłem domyślne komórki tabelki z datami , a potem zastąpiłem każdą komórkę w tabeli kontrolką hiperlink , która wywoła funkcje „SetDate()”. Oczywiście każda komórka przekazuje inny parametr daty do tej funkcji.

wywołanie mojego okna mycustomdatepicker

Jak działa ten przykład jeszcze raz? Użytkownik klikając na obrazek wywołuje okno dialogowe z kalendarzem, a w nim klika na konkretną datę i ta data jest wyświetliwana w odpowiednim formacie w textbox-ie.

Wady tego rozwiązania:

  • Pisanie własnego kodu? O ile jest to wada.

Następną opcją tego rozwiązania jest kontrolka DatePicker, która znajduję się w Ajaxowej bibliotece ASP.NET.

2. Ajax Control Toolkit

Zanim zaczniemy cokolwiek robić warto przedstawić , jak w prosty sposób dodać biblioteki AjaxControlToolkit do naszego projektu. Kiedy stawiałem pierwsze kroki w ASP.NET instalacja tego toolkitu pochłonęła kilka godzin mojego czasu. Na szczęście dzisiaj nie musimy już pobierać tych bibliotek i dodawać ich referencji z palca.

Microsoft całkiem niedawno dołączył do Visual Studio dodatek NuGet. W wielkim skrócie za pomocą tego dodatku w łatwy i przyjemny sposób możemy dodawać biblioteki, które pochodzą z sieci. Jakby tego było mało zawsze będziemy mieli najświeższą wersje tych niestandardowych bibliotek. Nie mówiąc o porządku w referencjach danego projektu, ponieważ wiemy skąd zostały dodane dane biblioteki.

Aby zainstalować Ajax Control Toolkit do projektu, to  klikamy prawym przyciskiem myszki na „References”.

Instalowanie AjaxControlToolkit

W oknie dialogowym wybieramy zakładkę „Online” i szukamy biblioteki „AjaxControlToolkit”.

instalowanie po przez NuGet 
Klikamy na przycisk „Install” i już mamy zainstalowany cały toolkit. Referencje oraz pewne wpisy do pliku web.config zostały dodane automatycznie, więc tylko tyle musieliśmy zrobić ,aby zainstalować ten framework.

Do tego przykładu wystarczy nam:

  • jedna strona ASP.NET
  • prosty textbox
  • kontrolka DatePicker z tego toolkitu
  • kontrolka ToolkitScriptManager do zarządzania skryptami tego toolkitu. Bez z niej użycie jakiejkolwiek kontrolki z tego toolkitu grozi rzuceniem wyjątku.

To wszystko.

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Rozwiazanie AjaxToolkit - CalendarExtender</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:TextBox ID="txtDate" runat="server"></asp:TextBox>
        <ajaxToolkit:CalendarExtender  ID="CalendarExtender1" TargetControlID="txtDate" runat="server" />
        <ajaxToolkit:ToolkitScriptManager runat="server" />
    </div>
    </form>
</body>
</html>

Działanie tego rozwiązania przestawia zrzut ekranu poniżej. Kliknięcie na textbox wywoła wewnątrz strony mały kalendarz.

AjaxToolkitExtenderControl

Oczywiście jeśli chcemy to możemy wywoływać okno kalendarza za pomocą kliknięcia na obrazek, tak jak zrobiliśmy to wcześniej. Wystarczy tylko obsłużyć właściwość PopupButtonID.
Więcej informacji o tej kontrolce można uzyskać tutaj.

Wady tego rozwiązania:

  • Ta technika jest zależna od ASP.NET AJAX wymagana jest jego instalacja na serwerze produkcyjnym.
  • Strona będzie wolniej działać z powodu skryptów.

Ostatnim podejściem do tego problemu jest użycie datepicker-a z jQuery.

3. jQuery DatePicker

Nie jestem wielkim fanem jQuery i obecnie znam ten framework tylko z nazwy ,ale nie przeszkodziło mi to w zrobieniu tego przykładu. Co udowadnia ,że jeśli ty też nigdy jeszcze nie korzystałeś z bibliotek JQuery to też teraz możesz to zrobić od zera.

W tym przypadku lepiej byłoby pobrać skrypty oraz style CSS bezpośrednio ze strony jQuery , ale chciałem sprawdzić na co stać dodatek NuGet w Visual Studio 2010. Czy można zainstalować tylko kontrolkę jQuery DatePicker za pomocą NuGet-a ależ oczywiście ,że tak?

Wystarczyło wpisać w polu wyszukiwani „datepicker”.

JQuery Datapicker 
Po instalacji do mojego projektu został dodany zestaw skryptów . Moje doświadczenie z jQuery można określić w minutach więc intuicyjne założyłem, że do datepicker będą mi potrzebne tylko dwa skrypty”jquery-1.4.4.m.in.js” oraz „jquery.ui.datepicker.js”. Być może dla wydajności strony można wybrać inne skrypty.

jquery js 

Strona wygląda tak.

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <link type="text/css" href="css/jquery-ui-1.7.1.custom.css" rel="stylesheet" />
    <script src="Scripts/jquery-1.4.4.min.js" type="text/javascript"></script>
    <script src="Scripts/jquery.ui.datepicker.js" type="text/javascript"></script>
    <SCRIPT type="text/javascript">
        $(function () {
            $("#txtDate").datepicker();
        });   
       </SCRIPT>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:TextBox ID="txtDate" ClientIDMode="Static" runat="server" ></asp:TextBox>
    </div>
    </form>
</body>
</html>

Od tej pory, tak jak w poprzednim ajaxowym przykładzie kliknięcie na pole tekstowe wywoła datepicker. Oczywiście NuGet zainstalował mi tylko skrypty więc rezultat początkowo wyglądał tak.

bez skórek

Chociaż jestem pełen podziwu ,że kontrolka się nie rozsypuje jeśli nie ma stylów CSS, postanowiłem jednak jakieś style znaleźć. Wybór jest naprawdę duży, więc zostawiam wolny wybór tutaj.

jquery calendar

Moja pierwsza 15-minutowa wędrówka do jQuery nie była wcale taka frustrująca. Kto wie być może kiedyś, będę musiał użyć tego pluginu, co będzie dobrą okazją do nauki. Teraz trochę rozumiem całą tę fascynację tym pluginem na całym świecie.


Zalety tego rozwiązania:

  • Kod tylko po stronie klienta.
  • 10.000 sposobów na przedstawienie kalendarza.
  • Wymaga tylko skryptów JavaScript ,a te mogą być cachowane.

Oto trzy różne sposoby na pobieranie dat od użytkownika. Wybierz jeden z nich i do dzieła.

Pobierz Kod