Расширение управляющего элемента LabelTextbox Практикум: продолжение примера создания управляющего элемента LabelTextbox ctLafelTextbox ШИШ Теперь можно протестировать свойства управля- ющего элемента. Повторите все шаги по созданию проекта в новом экземпляре Visual Studio, в котором Существует управляющий элемент LabelTextbox. Затем перенесите управляющий элемент в форму. Надпись с именем управляющего элемента и тексто- вое окно занимают всю оставшуюся площадь управ- ляющего элемента. Обратите внимание на то, что управляющие элементы, расположенные внутри управляющего элемента LabelTextbox, занимают правильные позиции, когда управляющий элемент добавляется к форме (см. рис. слева). Добавление новых свойств На данном этапе практически ничего нельзя де- лать с помощью названного управляющего элемента, поскольку у нас отсутствует возможность изменять текст надписи и текст в окне. Для работы с этим текстом мы добавим два свойства: LabeiText и TextBoxText. Эти свойства добавля- ются точно так же, как и два предыдущих свойства: public string LabeiText get • return IblTextBox.Text; set IblTextBox.Text = value; MoveControls(); // Метод MoveControls вызывается для изменения //размеров Textbox при наличии такой необходимости public string TextboxText get: { return txtLabelText.Text; 382 Глава 14 set txtLabelText.Text = value; > Если возникает необходимость включить некоторый текст, то мы просто при- сваиваем соответствующий текст надписи и свойству Text текстового окна и воз- вращаем значение названных свойств. Если текст надписи будет изменен, нам потребуется обратиться к методу MoveControisO , поскольку этот текст может ока- зывать влияние на то, каким образом будет располагаться текстовое окно. С дру- гой стороны, текст, включаемый для вывода в текстовом окне, не приводит к перемещению управляющих элементов, и в том случае, если он окажется длин- нее, чем текстовое окно, то он просто перестанет быть видимым. Добавление новых обработчиков событий Поскольку данный управляющий элемент является производным от класса userControi, он наследует от него большое количество функциональных возмож- ностей. Существует, однако, определенное количество событий, которые мы не же- лаем передавать пользователю стандартным способом. Среди них можно назвать Такие события, как KeyDown, KeyPress И KeyUp. Причина, ПО КОТОрОЙ нам необхОДИ- мо внести определенные изменения в эти события, заключается в том, что пользо- ватель предполагает, что они будут отправляться в тот момент, когда он нажимает какую-либо клавишу в текстовом окне. А в том виде, в котором они существуют сейчас, эти события будут отправляться только в том случае, если сам управляю- щий элемент находится в фокусе и пользователь нажимает клавишу. Для того чтобы изменить такое поведение, мы должны самостоятельно обраба- тывать события, отправляемые текстовым окном, а затем переправлять их далее пользователю. Сначала нам необходимо подписаться на соответствующие события в конструкторе формы: // Обработка события SizeChanged this.SizeChanged += new System.EventHandler(this.OnSizeChanged); // Обработка событий в Textbox, связанных с клавиатурой this.txtLabelText.KeyDown += new KeyEventHandler(this.txtLabelText_KeyDown); this.txtLabelText.KeyUp += new KeyEventHandler(this.txtLabelText__KeyUp) ; this.txtLabelText.KeyPress += new KeyPressEventHandler (this.txtLabelText__KeyPress) ; Затем следует добавить три обработчика событий: private void txtLabelТехt_KeyDown(object sender, KeyEventArgs e) OnKeyDown(e); private void txtLabelText_KeyUp(object sender, KeyEventArgs e) OnKeyUp(e); private voidtxtLabelText_KeyPress(object sender, KeyPressEventArgs e) OnKeyPress (e) ; Вызов метода опкеуххх формирует обращение к любому методу, который подписан на данное событие. Дополнительные возможности Windows Form 383 Добавление специально созданного обработчика событий Если требуется создать событие, которого не существует ни в одном из базовых классов, то придется выполнить несколько более серьезную работу. Мы создадим событие с именем Positionchanged (позиция изменена), которое будет возникать, когда изменяется значение свойства Position. Для создания такого события потребуется три вещи: • Нам будет необходим соответствующий делегат, который можно использовать для вызова методов, впоследствии привязываемых пользователем к событию. • Пользователь должен обладать возможностью подписаться на событие посредством привязки к нему некоторого метода. • Мы должны вызвать метод, который пользователь привязал к данному событию. В данном случае мы будем использовать делегат EventHandier, предоставляемый нам системой .NET Framework. Это делегат особого вида, который объявляется с помощью своего собственного ключевого слова — event. Следующий код объяв- ляет событие и предоставляет пользователю возможность на него подписаться: public event System.EventHandier PositionChanged; // Конструктор public ctlLabelTexboxO { . Теперь осталось только сгенерировать событие. Поскольку оно должно возни- кать в момент изменения значения свойства Position, мы генерируем событие В ОПИСателе ДОСТупа set К СВОЙСТВУ Position.* public PositionEnum Position { get { return mPosition; } set { mPosition = value; MoveControls(); if (PositionChanged i= null) // Убеждаемся в наличии подписчиков ' : // Получаем список методов, которые необходимо вызвать System.Delegate[] subscribers = PositionChanged.GetlnvocationList(); // Проходим в цикле по всем методам foreach (System.EventHandier target in subscribers) { target (this, new EventArgsO) ; // Вызываем очередной метод Сначала нужно убедиться в наличии каких-либо подписчиков на данное событие, проверяя, не равняется ли значение PositionChanged null. Если нет, то мы вызы- ваем метод GetlnvocationList, который позволяет получить список делегатов, 384 Глава 14 подлежащих вызову. После этого мы в цикле проходим по всем делегатам, вызы- вая каждый из них по очереди. Подписка на созданное нами событие осуществляется в конструкторе проекта LabelTextboxTest: public Forml() { // // Требуется для поддержки Windows Form Designer // InitializeComponent(); myControl.PositionChanged += new EventHandler(this.myControl_PositionChanged); Теперь можно откомпилировать и запустить тестовое приложение, содержащее созданный нами пользовательский управляющий элемент. Указанное приложение содержит также кнопку, которая изменяет внешний вид управляющего элемента, устанавливая и переустанавливая свойство Position, выводя при этом окно с со- общением. ех! Changed OK Ж*}- • exl ок buttoni Полный текст программ данного проекта может быть найден на web-сайте из- дательства Wrox. Данный пример может быть несколько усовершенствован, но мы оставим это для вас в качестве упражнения. Итоги В настоящей главе мы начали с того, на чем остановились в предыдущей, — с изучения управляющих элементов MainMenu и Toolbar. Мы познакомились с тем, каким образом можно создавать MDI- и SDI-приложения и каким образом в этих приложениях могут использоваться меню и панели инструментов. Затем мы пере- шли к созданию своих собственных управляющих элементов, к разработке их свойств, пользовательского интерфейса и событий для таких управляющих элементов. Дополнительные возможности Windows Form 385 В следующей главе обсуждение Windows Forms будет завершено рассмотрением одной особой разновидности формы, которая известна нам пока только по назва- нию — Windows Common Dialog. Упражнение Используя пример LabeiTextbox в качестве основы, создайте новое свойство с именем MaxLength (максимальная длина) для хранения максимально допустимого количества символов, которые могут находиться в текстовом окне. Затем создайте два новых события с именами MaxLengthchanged (максимальная длина изменена) и MaxLengthReached (максимальная длина достигнута). Событие MaxLengthchanged должно возникать при изменении значения свойства, а событие MaxLengthReached — в тот момент, когда пользователь вводит символ, с учетом которого длина текста В теКСТОВОМ ОКНе СТаНОВИТСЯ раВНОЙ Значению MaxLength.
|