- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания C# для профессионалов. Том II - Симон Робинсон
Шрифт:
Интервал:
Закладка:
□ Создание более развитых элементов управления
Конечный пример будет элементом управления выбором, который разрешает пользователю голосовать за одну из нескольких возможностей, и выводить графически результаты голосования. Варианты выбора будут определяться с помощью вложенных элементов управления потомков способом, описанным ранее.
Создадим для начала простой производный элемент управления.
Производный элемент управления RainbowLabel
Для этого первого примера создадим производный элемент управления из элемента управления Label и переопределим его метод Render() для вывода многоцветного текста. Чтобы держать элементы управления примера в этой главе отдельно, создадим новые файлы исходного кода, поэтому для этого элемента управления создадим новый файл .cs с именем RainbowLabel.cs и введем в него следующий код:
namespace PCSCustomWebControls {
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.Drawing;
public class RainbowLabel : System.Web.UI.WebControls.Label {
private Color[] colors = new Color[] {
Color.Red, Color.Orange, Color.Yellow,
Color.GreenYellow, Color.Blue, Color.Indigo, Color.Violet
};
protected override void Render(HtmlTextWriter output) {
string text=Text;
for (int pos=0; pos < text.Length; pos++) {
int rgb = colors[pos % 7].ToArgb() & 0xFFFFFF;
output.Write("<font color="#" + rgb.ToString("X6") + "'>" + text[pos] + "</font>");
}
}
}
}
Этот класс выводится из существующего элемента управления Label (System.Web.UI.WebControls.Label) и не требует никаких дополнительных свойств, так как достаточно унаследованного свойства Text. Мы добавили новое скрытое поле — colors[], которое содержит массив цветов, циклически изменяющихся при выводе текста.
Основная функциональность элемента управления находится в Render(), который переопределен, так как мы хотим изменить вывод HTML. Здесь мы берем строку для вывода из свойства Text и выводим каждый символ цветом из массива colors[].
Чтобы протестировать этот элемент управления, необходимо добавить его к форме в PCSCustomWebControlsTestApp:
<form method="post" runat="server" ID="Form1">
<PCS:RainbowLabel Runat="server" Text="Multicolored label!"
ID="rainbowLabel1" />
</form>
Нам нужно также добавить подходящее объявление в код, реализующий форму (если оно не добавится автоматически):
public class WebForm1 : System.Web.UI.Page {
protected RainbowLabel rainbowLabel1;
...
В результате будет получено:
Поддержание состояния в специальном элементе управления
Каждый раз при создании элемента управления на сервере в ответ на запрос к серверу, он создается с самого начала. Это означает что любое простое поле элемента управления будет повторно инициализироваться. Чтобы элементы управления поддерживали состояние между запросами, они должны использовать ViewState, о чем требуется помнить при создании элементов управления.
Чтобы проиллюстрировать это, добавим дополнительное свойство в элемент управления RainbowLabel. Мы добавив метод с именем Cycle(), который циклически перебирает доступные цвета и использует хранимое поле offset для определения цвета первой буквы выводимой строки.
Это поле должно использовать ViewState элемента управления, чтобы быть устойчивым между запросами. Если это не сделано и поле инициализируется в элементе управления, то все будет работать неправильно.
Здесь будет показан код для обоих случаев, чтобы увидеть ловушку, в которую очень легко попасть. Сначала мы посмотрим на код, который не может воспользоваться ViewState:
public class RainbowLabel : System.Web.UI.WebControls.Label {
private Color[] colors = new Color[] {
Color.Red, Color.Orange, Color.Yellow,
Color.GreenYellow, Color.Blue, Color.Indigo, Color.Violet
};
private int offset = 0;
protected override void Render(HtmlTextWriter writer) {
string text = Text;
for (int pos = 0; pos < text.Length; pos++ ) {
int rgb = colors[(pos + offset) % 7].ToArgb() & 0xFFFFFF;
output.Write("<font color= '#" + rgb.ToString("X6") + "'>" + text[pos] + "</font>");
}
}
public void Cycle() {
offset = ++offset % 7;
}
}
Здесь мы инициализируем поле offset нулем, а затем позволяем методу Cycle() увеличивать его. Использование оператора % гарантируем, что оно уменьшится до 0, если достигнет 7.
Чтобы протестировать это, требуется способ вызова метода Cycle() и добавление кнопки к форме:
<form method="post" runat="server" ID="Form1">
<PCS:RainbowLabel Runat="server" Text="Multicolored label!"
ID="rainbowLabel1" />
<asp:Button Runat="server" ID="cycleButton"
Text="Cycle colors" OnClick="cycleButton_Click" />
</form>
Co следующим обработчиком событий:
protected void cycleButton_Click(object sender, System.EventArgs e) {
this.rainbowLabel1.Cycle();
}
Если выполнить этот код, то окажется, что цвета изменяются при первом нажатии кнопки, но дальнейшие нажатия будут оставлять цвета без изменений.
Если этот элемент управления сохраняет себя на сервере между запросами, то он работает правильно, так как поле offset поддерживает свое состояние, не требуя специального внимания. Однако эта техника не имеет смысла для приложения Web, когда потенциально тысячи пользователей используют его одновременно. Создание отдельного экземпляра для каждого пользователя только ухудшает ситуацию.
В любом случае решение достаточно просто. Мы должны использовать свойство ViewState элемента управления для сохранения и извлечения данных. Нам не нужно беспокоиться о том, как это сериализуется, создается заново или о чем-то еще, мы просто помещаем данные в свойство и извлекаем данные, уверенные, что состояние будет поддерживаться между запросами стандартными средствами ASP.NET.
Чтобы поместить поле offset в ViewState, мы используем следующий код:
ViewState["_offset"] = offset;
ViewState состоит из пар имя-значение, и в данном случае используется имя _offset. Нам не нужно объявлять его где-либо, оно будет создано при первом использовании этого кода.
Аналогично для извлечения состояния используется код:
offset = (inc)ViewState["_offset"];
Если мы сделаем это, когда ничего не хранится в ViewState под этим именем, то будет получено значение null. Простейший способ справиться с такой ситуацией — использовать вызов в блоке try.
Собирая все вместе, сделаем следующие изменения в коде:
public class RainbowLabel : System.Web.UI.WebControls.Label {
private Color[] colors = new Color[] {
Color.Red, Color.Orange, Color.Yellow,
Color.GreenYellow, Color.Blue, Color.Indigo, Color.Violet
};
private int Offset;
protected override void Render(HtmlTextWriter writer) {
string text = Text;
GetOffset();
for (int pos = 0; pos < text.Length; pos++) {
int rgb = colors[(post + offset) % 7].ToArgb() & 0xFFFFFF;
writer.Write("<font color='#" + rgb.ToString("X6") + "'>" + text[pos] + "</font>");
}
}
private void GetOffset() {
try {
offset = (int)ViewState["_offset"],
} catch {
offset = 0;
}
}
public void Cycle() {
GetOffset();
offset = ++offset % 7;
ViewState["_offset"] = offset;
}
}
Теперь элемент управления позволит методу Cycle() работать каждый раз. Обычно ViewState используется для простых свойств, таких как свойства string:
public string Name {
get {
return (string)ViewState["_name"];
}
set {
ViewState["_name"] = value;
}
}
Еще одно замечание об использовании ViewState имеет отношение к элементам управления-потомкам. Если элемент управления имеет потомков и используется на странице больше одного раза, то возникает проблема, связанная с тем, что потомки будут по умолчанию сообща использовать свой ViewState. Практически в каждом случае это не то поведение, которое требуется, и к счастью мы имеем простое решение. Выводя элемент управления-предок из INamingContainer мы вынуждаем элементы управления-потомки использовать квалифицированное хранилище в ViewState, так что элементы управления-потомки не будут сообща использовать свой ViewState с аналогичными элементами управления-потомками с другим предком.
Использование этого интерфейса не требует никакой дополнительной реализации, нам нужно просто сказать, что мы его используем, как если бы это был просто маркер для интерпретации сервером ASP.NET. Мы сделаем это в следующем разделе.