Страница 9 из 15
2.3. Контроль за состоянием подчиненного окна. Воздействие подчиненного окна на главное
Для окна MainWindow измените обработчик button1_Click:
Для окна Window1 определите обработчик события IsVisibleChanged:
Результат. Заголовок кнопки button1 главного окна и действия при ее нажатии зависят от того, отображается на экране подчиненное окно win1 или нет. Подчиненное окно можно закрыть не только с помощью кнопки button1 главного окна, но и любым стандартным способом, принятым в Windows (например, с помощью комбинации клавиш Alt+F4); при любом способе закрытия подчиненного окна заголовок кнопки button1 будет изменен. Подчеркнем, что изменять надпись на кнопке button1 в обработчике button1_Click не следует именно по той причине, что закрыть подчиненное окно можно не только с помощью этой кнопки.
Комментарий
В то время как главное окно для доступа к подчиненному может просто обратиться к нему по имени, подчиненное окно так сделать не может, поскольку имя главного окна ей неизвестно (главное окно в нашем проекте имени вообще не имеет). Однако подчиненное окно может обратиться к главному, используя свое свойство Owner. Для доступа к конкретному компоненту главного окна, имеющему имя, мы воспользовались методом FindName. Можно было поступить по-другому: выполнить явное приведение объекта Owner к типу MainWindow и после этого обратиться к его свойству button1:
2.4. Окно с содержимым в виде обычного текста
В начало описания класса Window1 добавьте поле
В имеющийся в классе Window1 обработчик Window_IsVisibleChanged добавьте следующий фрагмент:
Результат. Текст подчиненного окна win1 содержит информацию о том, сколько раз оно было открыто. При изменении размеров подчиненного окна положение находящегося на нем текста изменяется так, чтобы он всегда оставался отцентрированным как по горизонтали, так и по вертикали относительно границ окна.
Комментарии
1. Добавленное в описание класса Window1 поле count при создании окна автоматически инициализируется нулем; в дальнейшем это поле можно вызывать из любого метода класса. Новые поля позволяют хранить дополнительную информацию о состоянии окна.
2. Напомним, что при использовании операции инкремента вида ++i вначале происходит увеличение значения переменной i на 1, а затем данная переменная используется в выражении. Для операции i++ действия выполняются в обратном порядке: вначале прежнее значение i используется в выражении, а затем это значение увеличивается на 1.
3. В данном случае содержимым окна является не группирующий, а «обычный» компонент. Особенностью использованного компонента TextBlock является то, что его содержимым может быть только строка (этот компонент не имеет свойства Content, зато имеет свойство Text типа string). Для обеспечения центрирования текста по обоим измерениям достаточно установить соответствующие значения свойств HorizontalAlignment и VerticalAlignment компонента TextBlock.
2.5. Модальные и обычные кнопки диалогового окна
Рис. 9. Макет окна Window2 приложения WINDOWS
В описание класса Window2 добавьте новое свойство, доступное только для чтения, и связанное с ним поле:
Определите три обработчика, которые уже указаны в xaml-файле:
Обратите внимание на то, что обработчик button2_Click должен иметь модификатор public (он выделен в тексте полужирным шрифтом).
В классе MainWindow дополните обработчик button2_Click:
Результат. Диалоговое окно win2 позволяет изменить заголовки главного и подчиненного окна. Заголовки окон изменяются либо при нажатии обычной кнопки «Применить», либо при нажатии модальной кнопки «OK» (в последнем случае диалоговое окно закрывается). Окно также закрывается при нажатии модальной кнопки «Отмена»; в этом случае заголовки окон не изменяются. Вместо кнопки «OK» можно нажать клавишу Enter, вместо кнопки «Отмена» – клавишу Esc.
Комментарии
1. Для того чтобы нажатие на кнопку «Отмена» приводило к закрытию диалогового окна (а также чтобы нажатие клавиши Esc интерпретировалось как нажатие на эту кнопку), для данной кнопки надо установить равным true свойство IsCancel. Для того чтобы кнопка «ОК» считалась кнопкой по умолчанию (и нажатие клавиши Enter интерпретировалось как нажатие на эту кнопку), для данной кнопки надо установить равным true свойство IsDefault. Заметим, что хотя кнопка «ОК» сделана кнопкой по умолчанию, для нее все равно необходимо определить обработчик события Click (для кнопки «Отмена» обработчик определять не требуется).
2. Доступ из окна win2 к свойству Title окна win1 возможен благодаря тому, что эти окна имеют общего владельца (Owner), который хранит список своих подчиненных окон (в порядке их добавления) в свойстве-коллекции OwnedWindows.
3. Включенное в класс Window2 свойство DialogRes позволяет определить способ закрытия диалогового окна: если окно было закрыто по нажатию кнопки «ОК», то свойство равно true, если окно было закрыто по нажатию кнопки «Отмена» (или каким-либо другим способом, например, по нажатию кнопки закрытия на заголовке окна), то свойство равно false. Это свойство проверяется в главном окне после возврата из метода ShowDialog.
Следует сказать, что метод ShowDialog из библиотеки WPF тоже возвращает значение, позволяющее определить, каким образом было закрыто диалоговое окно (это значение имеет тип bool?, т. е. может быть равно true, false и null, и определяется по значению стандартного свойства окна DialogResult того же типа), однако данный механизм корректно работает только в ситуации, когда диалоговое окно действительно закрывается, а не просто удаляется с экрана, как в нашем случае.
4. Явный вызов метода button2_Click класса Window2 в обработчике button2_Click класса MainWindow обеспечивает выполнение действий, связанных с нажатием на кнопку «Применить» (таким образом, данный вызов имитирует нажатие на кнопку). При вызове этого метода в качестве параметров указаны константы null, так как значения параметров в методе button2_Click класса Window2 не используются.
Для возможности вызова метода button2_Click класса Window2 из класса MainWindow модификатор доступа для данного метода необходимо изменить с private на public или internal (модификатор internal обеспечивает доступ к данному методу в пределах создаваемого проекта).
Заметим, что в данном случае можно было бы обойтись без модификации метода button2_Click класса MainWindow: достаточно просто вызывать метод button2_Click класса Window2 в уже имеющемся обработчике button1_Click этого же класса Window2: