Чтение онлайн

на главную

Жанры

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

5) в эту заготовку надо ввести код, который будет выполняться при нажатии кнопки button1; мы добавим в нее единственный оператор:

Заметим, что соответствующее изменение будет внесено и в xaml-файл:

Именно благодаря заданию атрибута Click в xaml-файле метод button1_Click будет связан с событием Click компонента button1 (при отсутствии такого атрибута метод button1_Click

будет считаться обычным методом класса, для выполнения которого требуется его явный вызов).

Описанный выше способ создания нового обработчика события был реализован еще для библиотеки Windows Forms. Однако в WPF-проекте имеется более быстрый способ определения нового обработчика, не требующий использования окна Properties. Необходимо ввести имя события как атрибут соответствующего элемента в xaml-файле (в нашем случае в элемент Button надо ввести текст «Click=», причем достаточно набрать несколько начальных символов имени события и воспользоваться для завершения набора выпадающим списком) и после появления рядом с набранным атрибутом выпадающего списка с текстом «New Event Handler» выбрать этот текст (если он еще не выбран) и нажать клавишу Enter. При этом в xaml-файл будет добавлено имя обработчика (в нашем случае button1_Click), а в cs-файле будет создана заготовка для обработчика с этим именем, хотя перехода к ней не произойдет, чтобы дать возможность продолжить редактирование xaml-файла. Если в программе уже имеются обработчики, совместимые с тем событием, имя которого введено в xaml-файле, то в выпадающем списке наряду с вариантом «New Event Handler» будут приведены и имена всех таких обработчиков, что позволит быстро связать события для нескольких компонентов с одним обработчиком (хотя для подобного связывания имеется более удобная возможность, основанная на механизме маршрутизируемых событий и описанная в проекте CALC).

Если для какого-либо компонента предполагается определять обработчики, то рекомендуется предварительно задать имя для этого компонента, чтобы оно включалось в имена созданных обработчиков.

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

Текст button1_Click мы не только выделяем полужирным шрифтом, но и подчеркиваем, чтобы отметить то обстоятельство, что этот текст будет автоматически сгенерирован редактором xaml-файлов после ввода текста Click= и выбора из появившегося списка варианта «New Event Handler» (напомним, что при этом в cs-файле будет создан новый обработчик с указанным именем).

Добавим к нашему проекту еще один обработчик – на этот раз для компонента Canvas (обратите внимание на то, что если обработчик создается для компонента, не имеющего имени, то в имени обработчика по умолчанию используется имя класса этого компонента):

Кроме того, необходимо задать фон для компонента Canvas:

Результат. Теперь после запуска программы при щелчке на любом месте окна кнопка «Закрыть» услужливо прыгает на указанное место. Нажатие на кнопку «Закрыть» приводит к завершению программы и возврату в среду Visual Studio.

Комментарии

1. Любой компонент WPF реагирует на нажатие мыши только в том случае, если имеет непустой фон. По умолчанию фон некоторых компонентов является пустым (в окне Properties в этом случае свойство Background имеет значение No Brush или вообще не содержит никакого текста). Следует заметить, что, несмотря на вид атрибута Background в xaml-файле, фон определяется не цветом, а особым классом WPF – кистью (имеется абстрактный класс Brush, от которого порождается несколько классов-потомков). Указание цветовой константы означает, что будет использоваться сплошная кисть типа SolidBrush с заливкой данного цвета. В последних проектах, описанных в данной книге (TRIGFUNC и HTOWERS), мы познакомимся с градиентной кистью, имеющей две

разновидности – LinearGradientBrush и RadialGradientBrush.

2. Важной характеристикой любого события, связанного с мышью, является позиция мыши. Для определения этой позиции в обработчиках мыши предусмотрен специальный метод, вызываемый для второго параметра обработчика e: e.GetPosition. Данный метод имеет обязательный параметр, задающий компонент, относительно которого определяется позиция мыши. Мы указали параметр this; это означает, что позиция будет определяться относительно левого верхнего угла клиентской области окна. Заметим, что все размеры в WPF задаются в так называемых аппаратно-независимых единицах (одна единица равна 1/96 дюйма) и представляются в виде вещественных чисел типа double (в то время как в библиотеке Windows Forms размеры задавались в экранно-зависимых пикселах и представлялись целыми числами).

3. Два последних оператора в обработчике Canvas_MouseDown демонстрируют способ, позволяющий задать в программе присоединенные свойства Left и Top, полученные компонентом от его родителя типа Canvas. Обратите внимание на то, что методы SetLeft и SetTop являются статическими и должны вызываться не для конкретного объекта типа Canvas, а для самого класса. Имеются парные методы Canvas.GetLeft(c) и Canvas.GetTop(c), позволяющие определить текущие значения свойств Left и Top для компонента c, расположенного на компоненте Canvas (эти методы будут использованы во фрагменте программы, добавленном в п. 1.5 при исправлении недочета).

Для задания присоединенных свойств можно также использовать «универсальный» метод SetValue, имеющийся у всех компонентов. Например, два последних оператора в обработчике Canvas_MouseDown можно изменить следующим образом:

Обратите внимание на то, что при указании присоединенного свойства в методе SetValue надо использовать его имя с суффиксом Property (на самом деле это и есть «настоящее» имя статического присоединенного свойства, поскольку подобный суффикс имеют все статические свойства зависимости). Интересно отметить, что с помощью метода SetValue с компонентом можно связывать любые свойства зависимости, определенные у любых типов компонентов (для получения значений этих свойств предназначен метод GetValue, пример использования которого приводится в последнем комментарии к п. 1.5).

4. Для определения текущих размеров компонента в программе надо обращаться к свойствам ActualWidth и ActualHeight. Свойства Width и Height для этого использовать нельзя, так как они обычно содержат лишь «рекомендованные» значения размеров, которые учитываются группирующими компонентами при компоновке своих дочерних компонентов (в частности, возможны рекомендованные значения «бесконечность» или NaN). В нашем случае свойства ActualWidth и ActualHeight кнопки используются для того, чтобы отцентрировать кнопку относительно курсора мыши.

1.4. Отсоединение обработчика от события

В начало описания класса MainWindow (перед конструктором public MainWindow) добавьте новое поле:

В окно добавьте новую кнопку button2, сделайте ее свойство Content пустой строкой и определите для этой кнопки два обработчика:

Результат. «Дикая» кнопка с пустым заголовком не дает на себя нажать, «убегая» от курсора мыши. Для того чтобы ее «приручить», надо переместить на нее курсор, держа нажатой клавишу Ctrl. После щелчка на дикой кнопке она приручается: на ней появляется заголовок «Изменить», и она перестает убегать от курсора мыши. Следует заметить, что приручить кнопку можно и с помощью клавиатуры, переместив на нее фокус с помощью клавиш со стрелками (или клавиши Tab) и нажав на клавишу пробела.

Недочет. Если попытаться «приручить» кнопку, переместив на нее фокус и нажав клавишу пробела, то перед приручением она прыгает по окну, пока не будет отпущена клавиша пробела. Причины такого поведения непонятны, поскольку нажатие клавиши пробела не должно приводить к активизации события, связанного с перемещением мыши. Следует, однако, отметить, что нажатие пробела обрабатывается в WPF особым образом, и по этой причине оно может приводить к таким странным эффектам.

Исправление. Дополните условие в методе button2_MouseMove:

Поделиться:
Популярные книги

Эфир. Терра 13. #2

Скабер Артемий
2. Совет Видящих
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Эфир. Терра 13. #2

Я – Орк. Том 3

Лисицин Евгений
3. Я — Орк
Фантастика:
юмористическое фэнтези
попаданцы
5.00
рейтинг книги
Я – Орк. Том 3

Охота на разведенку

Зайцева Мария
Любовные романы:
современные любовные романы
эро литература
6.76
рейтинг книги
Охота на разведенку

СД. Восемнадцатый том. Часть 1

Клеванский Кирилл Сергеевич
31. Сердце дракона
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
6.93
рейтинг книги
СД. Восемнадцатый том. Часть 1

Решала

Иванов Дмитрий
10. Девяностые
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Решала

Назад в СССР: 1986 Книга 5

Гаусс Максим
5. Спасти ЧАЭС
Фантастика:
попаданцы
альтернативная история
5.75
рейтинг книги
Назад в СССР: 1986 Книга 5

Титан империи 5

Артемов Александр Александрович
5. Титан Империи
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Титан империи 5

Сыночек в награду. Подари мне любовь

Лесневская Вероника
1. Суровые отцы
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Сыночек в награду. Подари мне любовь

Прометей: повелитель стали

Рави Ивар
3. Прометей
Фантастика:
фэнтези
7.05
рейтинг книги
Прометей: повелитель стали

Вдова на выданье

Шах Ольга
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Вдова на выданье

Старатель 3

Лей Влад
3. Старатели
Фантастика:
боевая фантастика
космическая фантастика
5.00
рейтинг книги
Старатель 3

Измена. Он все еще любит!

Скай Рин
Любовные романы:
современные любовные романы
6.00
рейтинг книги
Измена. Он все еще любит!

Темный Патриарх Светлого Рода 3

Лисицин Евгений
3. Темный Патриарх Светлого Рода
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Темный Патриарх Светлого Рода 3

Никто и звать никак

Ром Полина
Фантастика:
фэнтези
7.18
рейтинг книги
Никто и звать никак