Оценить:
 Рейтинг: 4.5

Разработка пользовательского интерфейса на основе технологии Windows Presentation Foundation

Год написания книги
2019
<< 1 ... 3 4 5 6 7
На страницу:
7 из 7
Настройки чтения
Размер шрифта
Высота строк
Поля

Мы избежали этой ошибки, добавив проверку в обработчик. Исправить подобную ошибку можно и другим способом: не добавляя проверку в метод textBox1_TextChanged, удалить оба атрибута TextChanged="textBox1_TextChanged" в xaml-файле и вместо этого добавить в конец конструктора MainWindow операторы

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

При анализе данного исправления возникает естественный вопрос: можно ли в программном коде связать требуемый обработчик с общим родителем обоих полей ввода – панелью StackPanel (подобно тому, как это делается в xaml-файле – см. комментарий 1)? Этому препятствуют два обстоятельства: во-первых, данная панель не имеет имени, с помощью которого к ней можно было бы обратиться в коде, и, во-вторых, в компоненте StackPanel отсутствует событие TextChanged. Первую проблему легко решить, добавив к описанию панели в xaml-файле атрибут x:Name. Вторая проблема решается благодаря наличию у любого компонента метода AddHandler, позволяющего связать с компонентом обработчик события даже в случае, если это событие для компонента не предусмотрено. Между прочим, первую из отмеченных проблем можно вообще не решать, если связать обработчик с родителем более высокого уровня – окном MainWindow. Таким образом, вместо указанных выше двух операторов достаточно добавить в конструктор окна следующий вызов метода AddHandler:

Обратите внимание на необходимость указания суффикса Event в первом параметре метода AddHandler и на более сложный способ определения второго параметра, требующий вызова конструктора класса, связанного с данным типом обработчиков событий.

4. Работа с датами и временем: CLOCK

Рис. 14. Окно приложения CLOCK

4.1. Отображение текущего времени

В список директив using в начале файла MainWindow.xaml.cs добавьте директиву:

В описание класса MainWindow добавьте поле

В конструктор класса добавьте следующие операторы:

Опишите в классе MainWindow обработчик события Tick для таймера (этот обработчик придется ввести полностью, вместе с его заголовком, так как заготовку для него нельзя создать с помощью окна Properties или xaml-файла):

Результат. При работе программы в ее окне отображается текущее время (рис. 15).

Рис. 15. Окно приложения CLOCK (первый вариант)

Комментарии

1. Для работы с датами и временем в библиотеке .NET предусмотрена структура DateTime. Ее статическое свойство Now, доступное только для чтения, возвращает текущую дату и время (по системным часам компьютера). Текущую дату без времени (время соответствует полуночи) можно получить с помощью статического свойства Today. Для преобразования даты/времени к их стандартным строковым представлениям можно использовать следующие методы структуры DateTime:

• ToShortDateString – дата в кратком формате «d», например «27.01.1756»;

• ToLongDateString – дата в полном формате «D», например «27 января 1756 г.»);

• ToShortTimeString – время в кратком формате «t», например «10:55»;

• ToLongTimeString – время в полном формате «T», например «10:55:15».

Метод ToString без параметров возвращает дату/время в формате «G» (дата в кратком формате, время в полном). Формат отображения даты/времени можно явно указать в методе ToString; например, в нашей программе можно было бы использовать такой вариант: DateTime.Now.ToString("T").

Упомянем еще некоторые форматы для даты/времени: «g» – дата и время в кратком формате, «F» – дата и время в полном формате, «f» – дата в полном формате, время в кратком, «M» или «m» – формат «месяц, день», «Y» или «y» – формат «месяц, год».

При форматировании дат используются текущие региональные настройки (в нашем случае – настройки для России), хотя имеется перегруженный вариант метода ToString, где можно явно указать требуемую региональную настройку. Можно также сменить региональную настройку для приложения в целом; для этого достаточно установить новое значение свойства CurrentCulture для объекта Thread.CurrentThread из пространства имен System.Threads. Например, для того чтобы установить для нашего приложения региональные настройки, соответствующие американскому варианту английского языка, достаточно добавить в конструктор следующий оператор:

При этом вариант отображения текущего времени в окне изменится (рис. 16).

Рис. 16. Окно приложения CLOCK с измененными региональными настройками

Заметим, что настройки для России имеют имя «ru-RU».

2. В отличие от библиотеки Windows Forms, где предусмотрен специальный невизуальный компонент Timer, в библиотеке WPF приходится использовать «обычный» объект типа DispatcherTimer (из пространства имен System.Windows.Threading), явным образом задавая в программе все его свойства и события. Обратите внимание на то, что свойство Interval (время между срабатываниями таймера) имеет тип TimeSpan (этот тип подробно описывается в последнем комментарии к следующему пункту).

3. Особенностью макета данного приложения является использование рамки Border вокруг метки с текстом текущего времени. Для отображения времени мы использовали специальную текстовую метку TextBlock, содержимым которой (в отличие от «обычной» метки Label) может быть только текст. В качестве имени для этого компонента мы выбрали label1 как более кратное и наглядное по сравнению с textBlock1.

Недочет. В течение первой секунды после запуска программы в метке сохраняется исходный текст «00:00:00», так как событие Tick возникает первый раз только через промежуток времени timer1.Interval, равный в нашем случае 1000 миллисекундам.

Исправление. Добавьте вызов обработчика для таймера в конструктор окна MainWindow:

4.2. Реализация возможностей секундомера

В классе MainWindow определите обработчики, уже добавленные в него в результате указания атрибутов Click в xaml-файле:

Кроме того, добавьте в класс MainWindow новое поле

а также дополните обработчик timer1_Tick:

Результат. При установке флажка Timer во включенное состояние программа переходит в режим секундомера, причем секундомер сразу запускается, отображая на экране секунды и десятые доли секунд (рис. 17). Запуск и остановка секундомера осуществляются по нажатию кнопки Start/Stop, сброс секундомера – по нажатию кнопки Reset. Доступны клавиши-ускорители: Alt+T (смена режима «часы/секундомер»), Alt+S (старт/остановка секундомера), Alt+R (сброс секундомера).

Рис. 17. Окно приложения CLOCK в режиме секундомера

Комментарии

1. Свойство IsChecked компонента CheckBox имеет в WPF тип bool?, т. е. может принимать три значения: true, false и null (последний вариант используется для флажков с тремя состояниями), поэтому в условии оператора if приходится выполнять приведение свойства checkBox1.IsChecked к типу bool (вместо этого можно использовать сравнение checkBox1.IsChecked = true).

2. Для формирования текста метки в режиме секундомера используется метод Format класса string, возвращающий строку, которая содержит фиксированные фрагменты и строковые представления различных объектов, отформатированные требуемым образом. Первым параметром данного метода является форматная строка, содержащая как обычный текст, так и форматные настройки для остальных параметров (количество подобных форматируемых параметров может быть произвольным). Форматные настройки заключаются в фигурные скобки {}; в нашем случае использованы простейшие форматные настройки, в которых задается только порядковый номер параметра, выводимого в указанной позиции форматной строки (в подобной простейшей ситуации для форматирования данного параметра автоматически вызывается его метод ToString). Параметры нумеруются от 0.

В версии C# 6.0, используемой в Visual Studio 2015, для формирования строк с различными «внешними» параметрами вместо метода Format удобнее применять так называемые интерполированные строки. В интерполированной строке перед открывающей ее двойной кавычкой указывается символ $; а параметры задаются в ней в фигурных скобках. С использованием интерполированной строки оператор задания текста метки в режиме секундомера можно представить в следующем виде:

Таким образом, интерполированная строка представляет собой форматную строку метода Format, в которой вместо порядкового номера выводимого параметра указывается сам этот параметр.

Недочет. При изменении режима изменяется ширина окна, «подстраиваясь» под текущий размер текста, выводимого на метке. Однако в данном случае изменение размеров окна не представляется оправданным. В частности, оно нарушит выравнивание окна по центру экрана. Кроме того, в режиме секундомера окно будет изменять размер во многих ситуациях, например, при переходе от 9 секунд к 10, от 99 секунд к 100, а также при сбросе значения секундомера.

Исправление. Добавьте к элементу Border в xaml-файле новый атрибут:

Результат. Теперь ширина окна остается неизменной в любом режиме.

Ошибка. Кажущаяся правильность работы секундомера обманчива. В этом можно убедиться, если не останавливать секундомер в течение некоторого времени (выполняя при этом другие действия на компьютере), после чего сравнить результат с точным временем. Причина заключается в том, что событие Tick наступает примерно


Вы ознакомились с фрагментом книги.
Приобретайте полный текст книги у нашего партнера:
<< 1 ... 3 4 5 6 7
На страницу:
7 из 7