Страница 4 из 15
Рис. 3. Окно дизайнера после удаления атрибутов компонента Canvas
Как правило, после добавления в окно какого-либо компонента путем его перетаскивания из панели Toolbox, всегда требуется выполнить действия, связанные с удалением «лишних» атрибутов.
Теперь добавим на компонент Canvas кнопку Button, зацепив ее мышью на панели Toolbox и перетащив в окно. После появления кнопки в окне следует перетащить ее в левый верхний угол окна (при подобном перетаскивании кнопка будет автоматически «притянута» к области, расположенной на расстоянии 10 единиц от левой и верхней границы клиентской области окна, – рис. 4).
Рис. 4. Окно дизайнера после добавления компонента Button
Содержимое xaml-файла изменится следующим образом:
Мы видим, что теперь элемент Canvas тоже оформляется в виде парных тегов, так как он содержит дочерний элемент – кнопку.
Обсудим атрибуты, автоматически добавленные к элементу Button. Атрибут с именем x:Name определяет имя, с помощью которого можно обращаться к данному компоненту в cs-файле. Это имя будет являться одним из свойств класса MainWindow. Обратите внимание на то, что элемент Canvas аналогичного имени не содержит. Это означает, что в классе MainWindow мы не сможем обращаться по имени к компоненту Canvas. Если это является неудобным, то всегда можно определить имя (или с помощью окна свойств, в котором свойство Name указывается первым, или непосредственно в xaml-файле).
Свойство Content определяет содержимое кнопки. В качестве значения свойства Content может указываться не только строка, но и любой компонент. Более того, на кнопку можно поместить группирующий компонент, в котором, в свою очередь, можно разместить любое количество других компонентов. Это позволяет создавать в WPF-приложении сложные интерфейсные элементы, конструируя их из базовых. Например, можно создать кнопку, содержащую не только текст, но и изображение (в дальнейшем мы воспользуемся этой возможностью – см., например, проект ZOO, п. 7.7).
Следует также обратить внимание на то, что для кнопки не указано свойство Height (хотя свойство Width имеется). Если свойство Height отсутствует, то высота компонента определяется по размерам его содержимого, что в большинстве случаев является оптимальным. Можно было бы удалить и свойство Width, тогда все размеры кнопки будут подстроены под ее содержимое, однако обычно свойство Width указывается, поскольку желательно, чтобы все кнопки в приложении имели одинаковую ширину.
В отличие от компонентов из библиотеки Windows Forms, компоненты библиотеки WPF не имеют свойств Top и Left, определяющих позицию, в которой они размещаются. Это связано с тем, что явное указание позиции компонентов в окне WPF обычно не требуется (положение компонентов определяется другими их свойствами, а также свойствами содержащих их группирующих компонентов). Однако для любого компонента можно задать свойства Top и Left, «полученные» от класса Canvas. Если данный компонент будет размещен на одном из компонентов типа Canvas, то эти полученные свойства будут учтены при определении его позиции. Возможность подобной «передачи» свойств от одного компонента к другому является одним из аспектов особого механизма, реализованного в WPF и связанного с так называемыми свойствами зависимости (dependency properties). Почти все свойства компонентов WPF являются свойствами зависимости, что позволяет их использовать при реализации различных возможностей, доступных в WPF, например, для привязки свойств или определения стилей. Частным случаем свойств зависимости являются присоединенные свойства (attached properties), которые, будучи определенными в одном классе, могут использоваться в другом. Свойства Top и Left компонента Canvas – типичный пример присоединенных свойств.
Присоединенные свойства панели Canvas особенно просто указывать в xaml-файле. Однако к ним можно обращаться и в программном коде, что будет продемонстрировано далее.
Итак, в результате добавления новых компонентов в окно наш xaml-файл изменился следующим образом:
Того же результата можно было достичь, просто введя данный текст в xaml-файл, хотя на практике оказывается более удобным добавлять новый компонент с помощью панели Toolbox, а уже затем редактировать связанный с ним текст, добавленный в xaml-файл.
Отредактируем полученный xaml-файл: изменим заголовок окна на текст «Прыгающие кнопки», надпись на кнопке – на «Закрыть», ее имя – на button1 (поскольку в дальнейшем мы добавим к окну еще одну кнопку). Кроме того, укажем для окна свойство WindowStartupLocation, положив его равным CenterScreen (это значение обеспечивает автоматическое центрирование окна программы при ее запуске):
Хотя свойства можно настраивать с помощью окна Properties, обычно бывает удобнее это делать непосредственно в xaml-файле. Более того, даже добавлять новые свойства в xaml-файл не составляет труда, так как при вводе уже нескольких начальных символов свойства появляется список всех свойств, начинающихся с этих символов, что позволяет быстро завершить ввод имени, нажав клавишу Tab, после чего в xaml-файл будет не только добавлено полное имя свойства, но и вставлены символы ="", а если свойство принимает фиксированный набор значений, то сразу отобразится список этих значений, из которых можно выбрать требуемый (мы могли это заметить, определяя свойство WindowStartupLocation).
В дальнейшем при описании действий, которые требуется выполнить для добавления в окно новых компонентов или изменения их свойств, мы будем просто указывать новое содержимое xaml-файла, выделяя в нем полужирным шрифтом новые или измененные фрагменты. Иногда (достаточно редко) мы будем также дополнительно помечать фрагменты, которые требуется удалить, оформляя их в виде перечеркнутого текста. Аналогичные способы выделения будем использовать и для фрагментов программного кода на языке C#.
Комментарий
При редактировании xaml-файла оказываются удобными две возможности, связанные с автоматическим добавлением или удалением закрывающих тегов.
(1) Если ввести новый открывающий тег, включая все его атрибуты, то после ввода закрывающей угловой скобки к открывающему тегу будет добавлен закрывающий, а курсор разместится между тегами.
Пример. Предположим, что был введен следующий текст (позиция курсора помечена символом |):
Если теперь ввести символ «>», то текст изменится следующим образом (символ | по-прежнему указывает на позицию курсора):
(2) Если перед закрывающей угловой скобкой открывающего тега ввести символ «/» (превратив этим действием тег в комбинированный), то соответствующий закрывающий тег будет удален из xaml-файла (при этом все дочерние элементы преобразованного элемента, если они имеются, станут элементами того же уровня, что и преобразованный элемент).
Пример. Если в тексте, полученном в предыдущем примере, перевести курсор на одну позицию влево
и ввести символ «/», то текст изменится следующим образом: