Для этого первого примера создадим производный элемент управления из элемента управления 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' />