ЖАНРЫ

Разработка пользовательского интерфейса на основе технологии Windows Presentation Foundation
Шрифт:
empty-line/>

Результат. При нажатии кнопки «=» указанное выражение вычисляется и отображается на экране (в метке label2). В качестве операнда при любой операции можно указывать число 0; при делении на 0 результатом является «–бесконечность» или «бесконечность» (в зависимости от знака первого операнда) или «NaN» («не число»), если первый операнд также равен 0. В случае если поля ввода содержат текст, который нельзя преобразовать в вещественное число, то выводится результат «ERROR».

Комментарии

1. При выполнении операций над числами типа double ошибок времени выполнения не возникает, однако результатом может быть одно из «особых» значений: double.NegativeInfinity (–), double.PositiveInfinity (+) и double.NaN («не число»).

2. Для преобразования строки в число можно использовать методы Parse и TryParse соответствующего числового типа. Метод TryParse следует применять, если возможна ситуация, когда требуемое преобразование окончится неудачей (при использовании метода Parse такая ситуация приведет к возбуждению исключения, для обработки которого потребуется писать дополнительный код; кроме того, обработка исключения требует существенно больше времени, чем обычная проверка с помощью условного оператора).

3. В методе button5_Click демонстрируются важные особенности, связанные с типом string. Во-первых, тип string можно использовать в качестве переключателя в операторе switch, во-вторых, для типа string определена операция +, в которой в качестве другого операнда (причем не обязательно второго) можно указывать выражение любого типа; при этом данное выражение автоматически преобразуется к типу string с помощью метода ToString, определенного для любого типа платформы .NET.

Ошибка. Отмеченный в конце предыдущего пункта недочет теперь приводит к неправильной работе программы. После нажатия на кнопку «=» символ «=» указывается между полями ввода; таким образом, информация о выбранной операции стирается, и при последующем нажатии кнопки «=» всегда выводится нулевой результат (для восстановления нормальной работы надо повторно выбрать требуемую операцию, нажав на связанную с ней кнопку). Обратите внимание на то, что в данном варианте программы при наступлении события Click для кнопки «=» выполняются два обработчика: button5_Click, который связан непосредственно с этой кнопкой, и button1_Click, связанный с ее родительским компонентом StackPanel. Поскольку событие Click является пузырьковым, вначале выполняется обработчик button5_Click.

Исправление. В начало метода button5_Click добавьте оператор

Комментарий

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

Итак, если для одного и того же туннелируемого или пузырькового события определен обработчик и в дочернем, и в родительском компоненте, то будут выполнены оба эти обработчика (причем порядок их вызова определяется категорией события). Однако имеется возможность прервать цепочку вызовов обработчиков данного события – для этого достаточно в одном из обработчиков пометить событие как обработанное описанным выше способом. Следует также заметить, что если туннелируемое событие (например, PreviewTextInput) помечено как обработанное, то не вызываются и все обработчики парного к нему пузырькового события (для события PreviewTextInput парным является TextInput). Соответствующий пример будет приведен в п. 3.4.

3.3. Простейшие приемы ускорения работы с помощью клавиатуры

Обратите внимание на добавленные символы подчеркивания в свойствах Content.

Результат. Кнопка «=» (button5) сделана кнопкой по умолчанию и отображается в окне особым образом (рис. 13); эквивалентом ее нажатия является нажатие на клавишу Enter. Символы, указанные на кнопках, подчеркиваются; это является признаком того, что с каждой кнопкой связана клавишаускоритель Alt+«подчеркнутый символ». Следует иметь в виду, что в последних версиях Windows символы, с которыми связываются клавиши-ускорители, подчеркиваются только в случае, если предварительно нажать клавишу Alt.

Рис. 13. Окно приложения CALC с подчеркнутыми символами в подписях кнопок

Комментарий

В WPF-проектах для выделения символов, с которыми требуется связать клавишу-ускоритель, необходимо указать перед ними символ подчеркивания «_» (в той редкой ситуации, когда символ подчеркивания требуется использовать в надписи на компоненте, надо ввести этот символ дважды). Заметим, что в проектах Windows Forms для связи символа с клавишей-ускорителем использовался символ «&». Он был заменен на символ «_», поскольку в xaml-файле (как и в любом XML-файле) символ «&» интерпретируется особым образом.

Ошибка. После нажатия на любую кнопку с арифметической операцией все последующие вычисления возвращают значение, равное 0 (поскольку первым символом метки label1 теперь является символ подчеркивания '_', не предусмотренный в операторе switch). Кроме того, символ операции, изображенный между полями ввода, тоже подчеркивается.

Исправление. Измените оператор в методе button1_Click следующим образом:

Комментарий

Для удаления одного или нескольких начальных символов строки достаточно вызвать метод TrimStart, указав удаляемые символы в качестве параметров (если параметры не указывать, то удаляются пробельные символы). Имеется также метод TrimEnd, удаляющий конечные символы, и метод Trim, удаляющий как начальные, так и конечные символы. Чтобы в нашем случае можно было использовать данный метод, необходимо выполнить явное преобразование свойства Content к типу string.

Недочет. Теперь, когда программа содержит средства для быстрого выполнения действий с помощью клавиатуры, более наглядно проявляется недочет, который имелся в ней с самого начала: при запуске данной программы в ней отсутствует компонент, имеющий фокус. Для того чтобы фокус появился на первом поле ввода (и при этом в нем отобразился вертикальный курсор), необходимо либо щелкнуть мышью на этом поле, либо нажать клавишу Tab. Было бы удобнее, если бы фокус устанавливался на первое поле ввода сразу после запуска программы.

Исправление. Добавьте в конструктор класса MainWindow оператор:

3.4. Использование обработчика событий от клавиатуры

Определите обработчик события PreviewTextInput для MainWindow:

Кроме того, измените метод button1_Click следующим образом:

Результат. Теперь для ввода любой операции достаточно нажать соответствующую клавишу (поскольку клавиша «–» может использоваться для ввода отрицательных чисел, в качестве ускорителя для кнопки «–» выбрана комбинация Shift+«–», соответствующая символу подчеркивания «_»). При вводе чисел игнорируются все клавиши, кроме цифровых, «–», «,» и Backspace (для обозначения символа, генерируемого клавишей Backspace, в C# можно использовать управляющую последовательность '\b'; нажатие этой клавиши обеспечивает удаление символа, расположенного слева от курсора в активном поле ввода).

Комментарии

1. При реализации описанных возможностей мы воспользовались тем, что событие PreviewTextInput является туннелируемым, т. е. вначале оно обрабатывается в родительском компоненте верхнего уровня (окне), а затем «спускается» по иерархии подчинения к тому компоненту, в котором возникло. Это позволило уже на уровне окна проанализировать введенный текст и выполнить требуемые действия по изменению арифметической операции (и, кроме того, «не пропустить» дальше те символы, которые не имеет смысла использовать в арифметических операндах). Напомним, что для прекращения последующих вызовов обработчиков данного события необходимо пометить событие как обработанное, положив свойство e.Handled равным true. Следует сказать, что пометка события как обработанного позволяет отменить вызов и стандартных обработчиков событий, связанных с компонентами (в нашем случае был отменен вызов стандартного обработчика события TextInput, обеспечивающего добавление набранного на клавиатуре символа в поле ввода).

2. Для имитации возникновения события, связанного с нажатием кнопок 1–4, в методе Window_PreviewTextInput вызывается обработчик данного события button1_Click. При этом необходимо указать нужную кнопку. Проще всего передать ее в качестве первого параметра обработчика, однако такой подход требует корректировки действий, содержащихся в методе button1_Click.

В операторе, добавленном в метод button1_Click, делается попытка привести параметр sender к типу Button. Если эта попытка успешна, то соответствующая кнопка помещается в переменную s. Если же указанное преобразование нельзя выполнить, то операция as возвращает значение null. Это означает, что обработчик был вызван родительским компонентом, а «истинный» адресат события содержится в свойстве e.Source, которое в этом случае приводится к типу Button и сохраняется в переменной s. Все описанные действия удалось реализовать в единственном операторе благодаря операции a ?? b, которая возвращает значение a, если оно не равно null, и b в противном случае.

Поделиться с друзьями: