Основы ASP.NET 2.0

         

Автоформатирование календаря


У календаря не один стиль, а несколько. Разные стили применяются к заголовку, к выходным и будним дням, дням нетекущих месяцев и к сегодняшнему дню. Стили можно задать как с помощью внешних классов, так и непосредственно. Все это просто поражает. Можно поставить календарь на тысячах разных сайтов, и везде он будет выглядеть по-разному.

В Visual Studio 2005 можно поменять внешний вид календаря с помощью предопределенных шаблонов. У многих элементов управления в режиме дизайна есть "умные ярлычки" (smart tags). В них есть ссылка на диалог автоформатирования календаря. При этом уже сделанные изменения свойств сохранятся.

Внешний вид календаря можно менять в обработчике события DayRender. У аргумента обработчика DayRenderEventArgs два свойства: Cell с типом TableCell — наследника WebControl и Day типа CalendarDay. В Cell можно добавлять новые элементы, но только такие, которые не запускают событий:

protected void calVoyage_DayRender(object sender, DayRenderEventArgs e) { if (e.Day.Date.Day == 8 && e.Day.Date.Month == 3) { e.Cell.BorderColor = System.Drawing.Color.Red; e.Cell.BorderWidth = 4; e.Cell.Controls.Add(new LiteralControl("<br>Без жен- щин жить нельзя")); } }

В этом примере проверяется день, и если это 8 марта, то вокруг него рисуется красная рамка. А еще добавляется элемент LiteralControl с текстом, соответствующим моменту.


Рис. 4.3. 



BulletedList


Этот элемент управления позволяет воспроизвести нумерованные и ненумерованные маркированные списки и добавляет к этому много новых возможностей. Это — новый элемент ASP .NET 2.0, который тоже может быть привязан к данным.

Тип списка определяется свойством BulletStyle. Список может быть пронумерован цифрами, буквами или латинскими числами либо же помечен маркерами разных форм:

<asp:BulletedList ID="BulletedList1" runat="server" BulletStyle="Numbered"> <asp:ListItem>Чебурашка</asp:ListItem> <asp:ListItem>Крокодил Гена</asp:ListItem> <asp:ListItem>Шапокляк</asp:ListItem> </asp:BulletedList>

Выглядит на странице как

ЧебурашкаКрокодил ГенаШапокляк

А его HTML-код

<ol id="BulletedList1" style="list-style-type:decimal;"> <li>Чебурашка</li><li>Крокодил Гена</li><li>Шапокляк</li>

Если свойство BulletStyle поменять на "Circle", то будет сгененирован ненумерованный список:

<ul id="BulletedList1" style="list-style-type:circle;"> <li>Чебурашка</li><li>Крокодил Гена</li><li>Шапокляк</li>

При значении CustomImage необходимо задать картинку в свойстве BulletImageUrl. Элементами списка могут быть гиперссылки и кнопки-гиперссылки:

<asp:BulletedList ID="BulletedListLinks" runat="server" BulletStyle ="Circle" DisplayMode="HyperLink"> <asp:ListItem Value="http://chebur.polyn.kiae.su">Чебурашка </asp:ListItem> <asp:ListItem Value="http://gena.crocodile.net">Крокодил Гена</asp:ListItem> <asp:ListItem Value="http://chapeauclack.com">Шапокляк </asp:ListItem> </asp:BulletedList>


Сами гиперссылки следует записывать в атрибут ListItem Value.

Тип LinkButton превращает пункты списка в гиперссылки, которые вызывают перезагрузку страницы. Обработчик нажатия на кнопки принимает аргумент, в котором содержится информация об индексе нажатого пункта:

<asp:BulletedList ID="BulletedListLinks" runat="server" BulletStyle ="Circle" DisplayMode="LinkButton" OnClick="BulletedListLinks_Click"> <asp:ListItem Value="Red">Красный</asp:ListItem> <asp:ListItem Value="Blue">Синий</asp:ListItem> <asp:ListItem Value="Green">Зеленый</asp:ListItem> </asp:BulletedList>

protected void BulletedListLinks_Click(object sender, BulletedListEventArgs e) { switch (e.Index) { case 0: BulletedListLinks.BackColor = System.Drawing.Color.LightCoral; break; case 1: BulletedListLinks.BackColor = System.Drawing.Color.Aqua; break; case 2: BulletedListLinks.BackColor = System.Drawing.Color.LightGreen; break; } }


Button




Button — это командная кнопка, нажатие на которую часто приводит к отправке данных на сервер. Можно создавать кнопки двух типов: для передачи данных формы (submit button) или командные кнопки для выполнения различных функций, связанных с данной кнопкой. Если на форме есть несколько кнопок, свойство CommandName позволяет узнать, какая именно кнопка была нажата.

ASP .NET поддерживает 3 вида событий.

События, которые происходят в браузере клиента и обрабатываются кодом на Javascript.События загрузки страницы.События элементов управления.

Например, чтобы обработать щелчок на кнопке, мы переопределяем событие Click.

protected void Button1_Click(object sender, EventArgs e) {

}

События можно определить через вкладку событий в окне свойств. Второй аргумент всех обработчиков событий имеет тип EventArgs или какой-либо унаследованный от него.

Например, мы хотим создать форму для заполнения резюме. Автор может иметь заранее неизвестное нам количество предыдущих мест работы. Добавим на форму кнопку, при нажатии на которую в форму добавляется один элемент ввода текста:

<%@ Page Language="C#"%> <script runat="server">

static int num=0; static TextBox[] tb=new TextBox[10]; void AddExperience(Object sender, EventArgs e) { if (num < 10) // Чтобы не возникало ошибки обращения к несуществующему элементу массива { TextBox newBox = new TextBox(); newBox.ID = "box" + num; tb[num] = newBox; num++; } for (int i=0; i<10; i++) // Добавление на форму контролов из массива. { if (tb[i] != null) { places.Controls.Add(tb[i]); Label lb=new Label(); lb.Text="<br><br>"; places.Controls.Add(lb); } else break; } }


</script> <html xmlns="http://www.w3.org/1999/xhtml" > <head> </head> <body> <form runat="server" id="Experience"> <asp:Label ID="Label1" runat="server" text=" Введите Ваше последнее место работы" /> <asp:Panel id="places" runat="server"> <asp:TextBox id="first" runat="server" /> <br /> <br /> </asp:Panel> <asp:Button id="Add" Text="Еще" OnCommand="AddExperience" CommandName="Add" runat="server" /> </form> </body> </html>

Здесь мы имеем массив из 10 элементов типа TextBox. Новый элемент создается в момент нажатия на кнопку "Еще". Можно добавить до 10 новых элементов. Как и раньше, они размещаются в контейнере, это нужно, чтобы они выводились до кнопки.

При помощи свойства OnClientClick можно задать клиентский сценарий на JavaScript. Его значением может быть встроенная функция языка JavaScript, или функция, описанная в теле страницы. Клиентский код выполняется до серверного кода, заданного в свойстве OnClick.


Calendar


Этот класс не имеет аналогов в HTML. Определив единственный элемент управления, можно создать и предоставить в распоряжение посетителей полноценный календарь, где они смогут прокручивать месяцы, выбирать день или неделю. Внешний вид этого элемента управления может быть самым разнообразным. И все это реализуется средствами HTML. Раньше это было возможно только с помощью ActiveX — контролов, которые нужно загружать с сервера, регистрировать в системе и проверять на безопасность.

Calendar имеет множество свойств.

CellPadding"Набивка" (расстояние между границами клетки и ее содержимым)
CellSpacingРасстояние между клетками
DayNameFormatСпособ написания названий дней недели. Может принимать значения FirstLetter, FirstTwoLetters, Full, Short
FirstDayOfWeekДля задания первого дня недели, Default — установки, принятые в системе
NextPrevFormatПоказ названий предыдущего и последующего месяцев. FullMonth — полное название, ShortMonth — первые 3 буквы, CustomText — любой текст, определенный программистом
SelectionModeСпособ выбора даты. Доступны Day, DayWeek, DayWeekMonth и None
ShowDayHeaderПоказывать ли названия дней недели (да по умолчанию)
ShowGridLinesПоказывать ли сетку (нет по умолчанию)
ShowTitleПоказывать ли заголовок (нет по умолчанию)
TitleFormatMonthYear, Month
TodaysDateКакая дата будет выбрана текущей. По умолчанию — дата на сервере
VisibleDateМесяц, который будет показан в календаре

Calendar поддерживает различные календарные системы — не только привычный григорианский, но и юлианский, иудейский, мусульманский, буддистский.


Это можно сделать, изменяя культурную информацию страницы.

Выбор клиентом даты начала путешествия на сайте туристического агентства:

<%@ Page Language="C#" %>

<script runat="server"> void Page_Load(Object sender, EventArgs e) { if (Page.IsPostBack) { TextToUser.Text = "Вы поедете " + calVoyage.SelectedDate.ToLongDateString();

} }

void calSelectChange(Object sender, EventArgs e) { if (calVoyage.SelectedDate > DateTime.Today) { TextToUser.Text = "Вы действительно хотите отпра- виться в путешествие " + calVoyage.SelectedDate.ToShortDateString() + "?"; Button ok = new Button(); ok.Width = 100; ok.Text = "Да"; form1.Controls.Add(ok); } else TextToUser.Text="Выберите будущую дату"; }

</script>

<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Пример календаря</title> </head> <body> <form runat="server" id="form1"> <asp:Calendar ID="calVoyage" runat="server" BackColor="lightgreen" CellPadding="3" CellSpacing="3" NextPrevFormat="FullMonth" SelectionMode="DayWeekMonth " OnSelectionChanged="calSelectChange" /> <asp:Label ID="TextToUser" runat="server" Font- Bold="True" Font-Underline="False" /><br> </form> </body> </html>

Если мы посмотрим на HTML-код страницы, которая сгенерирована этой программой, то увидим довольно объемный текст, в том числе функцию на JavaScript и большую таблицу, каждая ячейка которой ссылается на эту функцию.



Было бы непросто написать все это самим.

Свойства SelectMonthText и SelectWeekText задают символы HTML, по умолчанию &gt; и &gt;&gt; эта последовательность отображается в символы >.

С событием выбора даты OnSelectionChanged связан обработчик calSelectChange. В нем мы сначала проверяем, является ли выбранная дата будущей по отношению к сегодняшнему дню. Если да, то создается новая кнопка для подтвержения выбранной даты.

Такая строка в Page_Load —

this.Culture=new CultureInfo("th-TH").ToString();

сделает календарь таким, какой принят в Таиланде. Не забудьте включить пространство имен глобализации:

%@Import Namespace= "System.Globalization" %

Свойство SelectionMode, равное DayWeekMonth, позволяет выбрать как конкретный день, так и неделю или месяц. Как же получить выбранный диапазон дат? SelectedDate возвращает только первый день диапазона. Для этого существует коллекция Calendar1.SelectedDates:

TextToUser.Text = "Вы пробудете в путешествии "; for (int i = 0; i < calVoyage.SelectedDates.Count; i++) { TextToUser.Text += calVoyage.SelectedDates[i].ToShortDateString() + "<br>"; }

А еще элегантнее будет написать так:

foreach ( DateTime i in calVoyage.SelectedDates) { TextToUser.Text += i.ToShortDateString() + "<br>"; }

Можно запретить пользователю выбирать прошлую дату. Для этого можно воспользоваться свойством IsSelectable:

if (e.Day.Date < DateTime.Now) { e.Day.IsSelectable = false; }


HyperLink и LinkButton


HyperLink — гиперссылка обычная или с картинкой. Они позволяют передвигаться по сайту или давать ссылку на другие сайты:

<asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl="~/Customer.aspx">HyperLink</asp:HyperLink>

Знак ~ обозначает корневой каталог текущего сайта.

LinkButton — это кнопка, которая выглядит как гиперссылка. Нажатие на нее приводит к перезагрузке страницы. В свойстве PostBackUrl можно задать адрес страницы, которая будет обрабатывать текущую.



Image


Элемент управления asp:image соответствует тегу img языка HTML. Его можно использовать для динамического добавления на страницу новых изображений. Вернемся к нашему туристическому агентству. Мы решили, что, когда клиент выбирает города, на страницу автоматически должна выводиться карта соответствующего города. Оставляем это в качестве упражнения. Карты городов можно найти через поисковую систему Яндекс.

<asp:Image> имеет свойства AlternateText, ImageUrl, ImageAlign

AlternateTextСоответствует атрибуту ALT тега IMG. Отображается, если показ картинок отключен или картинки невозможно найти
ImageUrlСоответствует атрибуту SRC тега IMG
ImageAlignСоответствует атрибуту ALIGN тега IMG

Как всегда, свойства можно менять из программы. Например, меняя значение ImageUrl, можно организовать просмотр множества картинок в виде слайд-шоу. Создайте директорию images и поместите в нее несколько картинок image1, image2 и так далее.

Напишем новую страницу:

<%@ Page Language="C#" %> <html xmlns="http://www.w3.org/1999/xhtml" > <head>

<script language="C#" runat="server"> public static int count=1; void NextImage(Object sender, EventArgs e) { count++; if(count==10) count=1; //циклический просмотр Image1.ImageUrl ="images/image"+count+".jpg"; } </script> </head>

<body> <form runat="server"> <h3>Image Example</h3> <asp:Image id="Image1" runat="server" ImageAlign="top" AlternateText="Картинки нет" height="300" ImageUrl="images/image1.jpg"/> <hr> <br><br> <asp:Button id="Next" Text="Next" OnClick="NextImage" runat="server"/> <br><br> </form> </body> </html>



ImageButton


Элемент управления ImageButton представляет собой комбинацию элементов Image и Button. Его можно использовать для создания изображений, чувствительных к клику мышки. Щелчок является событием, при наступлении которого выполняется некоторый код:

<asp:ImageButton id="imgButton" OnCommand ="SubmitPartl" runat="server" />

ImageButton позволяет достичь эффекта, аналогичного карте изображения. Событие Click позволяет узнать координаты щелчка мыши и реагировать соответственно региону, в котором была нажата мышь. Обработчик события должен принимать аргумент типа ImageClickEventArgs — наследника System.EventArgs. У него есть дополнительные поля X и Y — координаты клика мышки:

protected void ImageButton1_Click(object sender, System.Web.UI.WebControls.ImageClickEventArgs e) { // обработка события }

Вернемся опять в туристическое агентство. Директор вызвал вас (программиста) и попросил воплотить следующее: на странице с изображением карты Каира необходимо сделать так, чтобы когда пользователь нажимал мышкой в любое место, открывалась карта района, на который он нажал. Всего имеется 9 районов. Все картинки имеют размер 300 на 300 пикселов. Районы одинаковые, расположены в таблице 3 на 3.

Вы пишете:

<%@ Page Language="C#" %> <script runat="server">

void Magnify(Object sender, ImageClickEventArgs e) { int x=e.X; int y=e.Y; int row=y/100; // строка, на которую кликнули int col=x/100; // столбец, на который кликнули

int count=row*3+col+1; //номер картинки plan.ImageUrl ="Cairo/map-"+count+".jpg"; plan.Enabled = false; // это нужно, чтобы не открывался другой район.


instruction.Text=" Нажмите Back, чтобы увидеть весь город"; } </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head> </head> <body> <form runat="server"> <h3>Карта Каира </h3> <br /> <br /> <asp:Label id="instruction" runat="server">Нажмите мышью на любой район, чтобы увеличить картинку.</asp:Label> <br /> <br /> <asp:ImageButton id="plan" onclick="Magnify" runat="serv- er" width="300" height="300" ImageUrl="Cairo/map.gif"></asp:ImageButton> <br /> <br /> </form> </body> </html>

А более простое использование — создание красивых нестандартных кнопок. Свойство CommandName используется так же, как и в случае с обычной кнопкой:

<form id="form1" runat="server"> <div> <asp:ImageButton ID="ImageButton1" runat="server" CommandName="create" ImageUrl="~/Images/1button-create.gif" OnCommand="ImageButton_Click" OnClientClick='alert("clicked")' ToolTip="Create very nice account" /> <asp:ImageButton ID="ImageButton2" runat="server" CommandName="add" ImageUrl="~/Images/1button-add.gif" OnCommand="ImageButton_Click" /> <asp:ImageButton ID="ImageButton3" runat="server" ImageUrl="~/Images/1button-cancel.gif" CommandName="cancel" OnCommand="ImageButton_Click" /><br /> <asp:Label ID="Message" runat="server"></asp:Label></div> </form>



Картинки этого примера есть в поставке Visual Studio 2005 Microsoft Visual Studio 8\Common7\IDE\ProjectTemplates\Web\CSharp\1033. Скопируйте их в папку Images вашего проекта и добавьте их в проект.

Эту функцию вставьте в файл отделенного кода:

protected void ImageButton_Click(Object sender, CommandEventArgs e) { switch (e.CommandName) { case "create":

// Insert code to create. Message.Text = "Creating "; break;

case "add":

// Insert code to add. Message.Text = "Adding "; break; case "cancel":

// Insert code to cancel. Message.Text = "canceling"; break; }

}

У первой кнопки установлено свойство ToolTip. Посмотрите страницу в Internet Explorer. Окно с подсказкой появится при наведении на эту кнопку. А вот Opera выводит подсказку для всех кнопок. Но для тех, в которых установлен ToolTip, он выводится на первой строчке. Во второй — адрес.


Рис. 4.1. 

У кнопки также показано использование свойства OnClientClick. Оно задает клиентский сценарий, который будет исполняться при нажатии на кнопку без обращения к серверу. Здесь это функция alert языка Javascript — вызов окна с уведомлением.


Literal


Если не требуется менять значение текста программно, можно использовать элемент управления Literal. В таком случае текст будет выводиться "как есть", без тегов <span>. Этот класс наследуется не от WebControl, а от Control, поэтому его можно ставить вне формы. Соответственно у него нет свойств, отвечающих за внешний вид и стиль. Это не страшно, стиль может быть определен в контейнере, в который он включен, — div или Panel. Зато есть интересное свойство Mode. Попробуем на примере:

<asp:Literal ID="Literal1" Runat="server" Mode="Encode" Text="<b>Here is some text</b>"></asp:Literal>

Mode="Encode" кодирует текст так, чтобы в браузере был виден именно этот HTML-код, заменяя специальные символы разметки CER-последовательностями:

&lt;b&gt;Label&lt;/b&gt;

Это полезно, если бывает нужно вывести код, и не только HTML. На некоторых сайтах, где есть учебники по С++ в plain text, в примерах кода встречается строка

#include

без имени включаемого файла. Оно было "съедено" браузером, который считает все в <> за тег, даже если не распознает его, хотя текст был заключен в <PRE></PRE>. Ну вот, этой проблемы можно избежать.



Отправка данных другой странице


В ASP .NET 1.1 не разрешалась отправка данных между страницами. В ASP .NET 2.0 элементы управления имеют свойство PostBackUrl, где можно указать, какой странице система должна передать Web-форму, если отправление данных на сервер инициировано этим элементом управления.

Через свойство PreviousPage страницы можно выяснить, какая страница была источником постбэка нашей страницы.

На первой странице рисуется календарь:

<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server"> </script>

<html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Первая страница</title> </head> <body> <form id = "form1" runat= "server"> Ваше имя:<br /> <asp:Textbox ID="TextBox1" Runat="server"> </asp:Textbox> <p> Желаемая дата вылета?<br /> <asp:Calendar ID="Calendar1" Runat="server"></asp:Calendar></p> <br /> <asp:Button ID="Button2" Runat="server" Text="Submit page to Page2.aspx" PostBackUrl="Page2.aspx" /> <p> <asp:Label ID="Label1" Runat="server"></asp:Label></p> </form> </body> </html>

А на второй читаются значения первой формы:


<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server"> protected void Page_Load(object sender, System.EventArgs e) { if (PreviousPage != null) { TextBox pp_Textbox1; Calendar pp_Calendar1; pp_Textbox1 = (TextBox)PreviousPage.FindControl("Textbox1"); pp_Calendar1 = (Calendar)PreviousPage.FindControl("Calendar1"); Label1.Text = "Здравствуйте, " + pp_Textbox1.Text + "!<br />" + "Вы выбрали: " + pp_Calendar1.SelectedDate.ToShortDateString(); } } </script>

<html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Вторая страница</title> </head> <body> <form id="form1" runat="server"> <div> <asp:Label ID="Label1" Runat="server"></asp:Label> </div> </form> </body> </html>


Table


Таблицы в HTML очень распространены, так как они позволяют позиционировать элементы на странице. Серверный элемент управления задается тегами <asp:Table ID="Table1" runat="server"></asp:Table>. Мощь ASP .NET проявляется при динамическом создании таблицы. Этот элемент управления в ASP .NET используется реже, так как элемент DataGrid позволяет получить те же результаты, имея к тому же привязку к данным.

Свойство Rows таблицы является контейнером строк — элементов TableRow, а они, в свою очередь, имеют свойство Cell — коллекцию элементов TableCell. Сам TableCell — контейнер любых элементов управления. Их нельзя вставлять в таблицу иначе, чем в один из элементов TableCell. Текст в ячейку можно записать через свойство Cell.Text или вставкой элемента Literal.

Строки таблицы могут быть также типа TableHeaderRow и TableFooterRow. Такие строки всегда отображаются на мобильных устройствах с небольшим экраном, даже если таблица большая и для ее просмотра нужна прокрутка. Ячейки таблицы могут быть типа TableHeaderCell — наследника TableCell. Текст в них отображается выделенным полужирным шрифтом и центрирован.

В ASP .NET 2.0 у элемента появилась возможность задавать заголовки с помощью свойства Caption. Местоположение заголовка определяется свойством CaptionAlign. При значении Bottom он будет находится под таблицей. При остальных значениях заголовок находится где ему положено — наверху, Left и Right просто выравнивают у левого или правого края.

Этот пример иллюстрирует создание таблицы в программном режиме.


Игра "Найди число" тренирует внимание и память. Вначале игрок вводит размер таблицы n. Программа генерирует квадратную таблицу, где числа от 1 до n^2 написаны на кнопках и перемешаны в случайном порядке.


Рис. 4.2. 

protected void Page_Load(object sender, EventArgs e) { int tableSize = 5; if (!Page.IsPostBack) { int[,] numbers = new int[tableSize, tableSize]; for (int i = 0; i < tableSize; i++) for (int j = 0; j < tableSize; j++) { numbers[i, j] = i * tableSize + j+1; } int current = tableSize * tableSize; Random r = new Random(); for (int i = 0; i < tableSize * tableSize / 2; i++) { //swap i and number int number = r.Next(1, current); int t = numbers[number / tableSize, number % tableSize]; numbers[number / tableSize, number % number] = numbers[i / tableSize, i % tableSize]; numbers[i / tableSize, i % tableSize] = t; current--; } Table Table1 = new Table(); Table1.CellSpacing = 0; Table1.CellPadding = 0; Table1.BorderWidth = 2; Table1.GridLines = GridLines.Both; for (int i = 0; i < tableSize; i++) { TableRow row = new TableRow(); for (int j = 0; j < tableSize; j++) { TableCell cell = new TableCell(); Button button = new Button(); button.Text = numbers[i, j].ToString(); button.OnClientClick = "return false"; button.Width = 26; button.Height = 26; cell.Controls.Add(button); cell.Height = 26; cell.Width = 26; row.Cells.Add(cell); } Table1.Rows.Add(row); } form1.Controls.Add(Table1); } } }


Мы рассмотрели только некоторые элементы


Мы рассмотрели только некоторые элементы управления и убедились, что они предоставляют богатые возможности. В следующей лекции мы рассмотрим другой важный класс элементов управления — валидаторы.