Общие сведения о диалоговых окнах
Автономные приложения обычно имеют главное окно, отображающее основные данные, с которыми приложение работает, и предоставляющее функциональные возможности для обработки этих данных с помощью механизмов пользовательского интерфейса (UI), таких как строки меню, панели инструментов и строки состояния. Нетривиальное приложение может также отображать дополнительные окна для следующих целей:
отображения определенных сведений для пользователей;
сбора сведений от пользователей;
сбора и отображения сведений.
Такие типы окон называются диалоговыми окнами, и они бывают двух типов: модальные и немодальные.
Модальное диалоговое окно отображается функцией, когда для продолжения ей требуются дополнительные данные от пользователя. Поскольку функция зависит от модального диалогового окна для сбора данных, это окно также не разрешает пользователю активизировать другие окна в приложении, пока остается открытым. В большинстве случаев модальное диалоговое окно разрешает пользователю сообщать о завершении работы с модальным диалоговым окном путем нажатия кнопки ОК или Отмена. Нажатие кнопки ОК указывает, что пользователь ввел данные и желает, чтобы функция продолжила работу с этими данными. Нажатие кнопки Отмена указывает, что пользователь хочет вообще остановить выполнение этой функции. Наиболее распространенными примерами модальных диалоговых окон являются окна, которые отображаются для открытия, сохранения и печати данных.
С другой стороны, немодальное диалоговое окно не запрещает пользователю активацию других окон, когда оно открыто. Например, если пользователь хочет найти вхождения конкретного слова в документе, главное окно часто открывает диалоговое окно с запросом слова для поиска. Так как поиск слова не мешает пользователю редактировать документ, диалоговое окно не обязательно должно быть модальным. Немодальное диалоговое окно содержит по крайней мере одну кнопку Закрыть для закрытия этого диалогового окна и может предоставлять дополнительные кнопки для выполнения определенных функций, например кнопку Найти далее для поиска следующего слова, соответствующего критерию поиска.
Windows Presentation Foundation (WPF) позволяет создавать разные типы диалоговых окон, включая окна сообщений, общие диалоговые окна и пользовательские диалоговые окна. В этом разделе рассматриваются все эти типы, а в разделе Примеры диалоговых окон приводятся соответствующие примеры.
Поля сообщения
Окно сообщения — это диалоговое окно, в котором можно отображать текстовую информацию и разрешать пользователям принимать решения с помощью кнопок. На следующем рисунке показано окно сообщения, в котором отображается текстовая информация, задается вопрос и предоставляются три кнопки для ответа на этот вопрос.
Чтобы создать окно сообщения, используйте класс MessageBox. Класс MessageBox позволяет настроить в окне сообщения текст, заголовок, значок и кнопки с помощью кода, подобного следующему.
// Configure the message box to be displayed
string messageBoxText = "Do you want to save changes?";
string caption = "Word Processor";
MessageBoxButton button = MessageBoxButton.YesNoCancel;
MessageBoxImage icon = MessageBoxImage.Warning;
' Configure the message box to be displayed
Dim messageBoxText As String = "Do you want to save changes?"
Dim caption As String = "Word Processor"
Dim button As MessageBoxButton = MessageBoxButton.YesNoCancel
Dim icon As MessageBoxImage = MessageBoxImage.Warning
Для отображения окна сообщения вызывается метод static
Show, как показано в следующем коде.
// Display message box
MessageBox.Show(messageBoxText, caption, button, icon);
' Display message box
MessageBox.Show(messageBoxText, caption, button, icon)
Когда коду, который показывает окно сообщения, нужно определить и обработать решение пользователя (какая кнопка была нажата), он может проверить результат окна сообщения, как показано в следующем коде.
// Display message box
MessageBoxResult result = MessageBox.Show(messageBoxText, caption, button, icon);
// Process message box results
switch (result)
{
case MessageBoxResult.Yes:
// User pressed Yes button
// ...
break;
case MessageBoxResult.No:
// User pressed No button
// ...
break;
case MessageBoxResult.Cancel:
// User pressed Cancel button
// ...
break;
}
' Display message box
Dim result As MessageBoxResult = MessageBox.Show(messageBoxText, caption, button, icon)
' Process message box results
Select Case result
Case MessageBoxResult.Yes
' User pressed Yes button
' ...
Case MessageBoxResult.No
' User pressed No button
' ...
Case MessageBoxResult.Cancel
' User pressed Cancel button
' ...
End Select
Дополнительные сведения об использовании окон сообщений см. в описании MessageBox и примере MessageBox и примере диалогового окна.
Хотя класс MessageBox может предоставлять простой пользовательский интерфейс диалогового окна, преимущество использования MessageBox заключается в том, что это единственный тип окна, который может отображать приложения, работающие в песочнице с частичным доверием (см. раздел Безопасность), такие как браузерные приложения XAML (XBAPs).
Большинство диалоговых окон отображают и собирают более сложные данные, чем результат окна сообщения, в том числе текст, выбранные варианты (флажки), взаимоисключающий выбор (переключатели) и списки выбора (списки, поля со списком, поля с раскрывающимся списком). Для этого Windows Presentation Foundation (WPF) предоставляет несколько общих диалоговых окон и позволяет создавать собственные диалоговые окна, хотя их использование возможно только в приложениях, выполняющихся с полным доверием.
Общие диалоговые окна
Windows реализует различные, многократно используемые диалоговые окна, которые являются общими для всех приложений, включая диалоговые окна для открытия файлов, сохранения файлов и печати. Поскольку эти диалоговые окна реализованы операционной системой, они могут совместно использоваться всеми приложениями, работающими в операционной системе, что помогает поддерживать единообразие пользовательского интерфейса; если пользователи знакомы с диалоговым окном, предоставляемым операционной системой в одном приложении, им не нужно учиться пользоваться этим диалоговым окном в других приложениях. Поскольку эти диалоговые окна доступны для всех приложений и обеспечивают согласованный пользовательский интерфейс, они называются общими диалоговыми окнами.
Windows Presentation Foundation (WPF) инкапсулирует общие диалоговые окна открытия файлов, сохранения файлов и печати и представляет их как управляемые классы для использования в автономных приложениях. В этом разделе приводится краткий обзор каждого типа диалоговых окон.
Диалоговое окно открытия файлов
Диалоговое окно открытия файлов, показанное на следующем рисунке, используется функциональностью открытия файла для получения имени открываемого файла.
Общее диалоговое окно открытия файла реализуется как класс OpenFileDialog и находится в пространстве имен Microsoft.Win32. Следующий код показывает, как создавать, настраивать и отображать такое окно, а также как обрабатывать результат.
// Configure open file dialog box
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
dlg.FileName = "Document"; // Default file name
dlg.DefaultExt = ".txt"; // Default file extension
dlg.Filter = "Text documents (.txt)|*.txt"; // Filter files by extension
// Show open file dialog box
Nullable<bool> result = dlg.ShowDialog();
// Process open file dialog box results
if (result == true)
{
// Open document
string filename = dlg.FileName;
}
' Configure open file dialog box
Dim dlg As New Microsoft.Win32.OpenFileDialog()
dlg.FileName = "Document" ' Default file name
dlg.DefaultExt = ".txt" ' Default file extension
dlg.Filter = "Text documents (.txt)|*.txt" ' Filter files by extension
' Show open file dialog box
Dim result? As Boolean = dlg.ShowDialog()
' Process open file dialog box results
If result = True Then
' Open document
Dim filename As String = dlg.FileName
End If
Дополнительные сведения о диалоговом окне открытия файла см. в статье Microsoft.Win32.OpenFileDialog.
Примечание.
OpenFileDialog может использоваться для безопасного извлечения имен файлов приложениями, выполняющимися с частичным доверием (см. раздел Безопасность).
диалоговое окно сохранения файлов
Диалоговое окно сохранения файлов, показанное на следующем рисунке, используется функциональностью сохранения файла для получения имени сохраняемого файла.
Общее диалоговое окно сохранения файла реализуется как класс SaveFileDialog и находится в пространстве имен Microsoft.Win32. Следующий код показывает, как создавать, настраивать и отображать такое окно, а также как обрабатывать результат.
// Configure save file dialog box
Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
dlg.FileName = "Document"; // Default file name
dlg.DefaultExt = ".txt"; // Default file extension
dlg.Filter = "Text documents (.txt)|*.txt"; // Filter files by extension
// Show save file dialog box
Nullable<bool> result = dlg.ShowDialog();
// Process save file dialog box results
if (result == true)
{
// Save document
string filename = dlg.FileName;
}
' Configure save file dialog box
Dim dlg As New Microsoft.Win32.SaveFileDialog()
dlg.FileName = "Document" ' Default file name
dlg.DefaultExt = ".txt" ' Default file extension
dlg.Filter = "Text documents (.txt)|*.txt" ' Filter files by extension
' Show save file dialog box
Dim result? As Boolean = dlg.ShowDialog()
' Process save file dialog box results
If result = True Then
' Save document
Dim filename As String = dlg.FileName
End If
Дополнительные сведения о диалоговом окне сохранения файла см. в статье Microsoft.Win32.SaveFileDialog.
Печать - диалоговое окно
Диалоговое окно печати, показанное на следующем рисунке, используется функциональными возможностями печати для выбора и настройки принтера, на котором пользователь хочет печатать данные.
Общее диалоговое окно печати реализуется как класс PrintDialog и находится в пространстве имен System.Windows.Controls. Следующий код показывает, как создавать, настраивать и отображать такое окно.
// Configure printer dialog box
System.Windows.Controls.PrintDialog dlg = new System.Windows.Controls.PrintDialog();
dlg.PageRangeSelection = PageRangeSelection.AllPages;
dlg.UserPageRangeEnabled = true;
// Show save file dialog box
Nullable<bool> result = dlg.ShowDialog();
// Process save file dialog box results
if (result == true)
{
// Print document
}
' Configure printer dialog box
Dim dlg As New PrintDialog()
dlg.PageRangeSelection = PageRangeSelection.AllPages
dlg.UserPageRangeEnabled = True
' Show save file dialog box
Dim result? As Boolean = dlg.ShowDialog()
' Process save file dialog box results
If result = True Then
' Print document
End If
Дополнительные сведения о диалоговом окне печати см. в статье System.Windows.Controls.PrintDialog. Подробное описание печати в WPF см. в разделе Общие сведения о печати.
Пользовательские диалоговые окна
Хотя общие диалоговые окна полезны и должны использоваться, когда это возможно, они не поддерживают требований диалоговых окон отдельного домена. В этих случаях необходимо создавать собственные диалоговые окна. Как мы увидим, диалоговое окно является окном со специальным поведением. В Window реализованы эти типы поведения. Поэтому с помощью класса Window можно создавать модальные и немодальные диалоговые окна.
Создание модального пользовательского диалогового окна
В этом разделе показано, как с помощью класса Window создать типовое модальное диалоговое окно, используя в качестве примера диалоговое окно Margins
(см. пример диалогового окна). Диалоговое окно Margins
показано на следующем рисунке.
Настройка модального диалогового окна
Пользовательский интерфейс для типичного диалогового окна включает следующее.
Различные элементы управления, которые необходимы для сбора нужных данных.
Кнопка ОК, которую пользователи нажимают для закрытия диалогового окна, возврата в функцию и продолжения обработки.
Кнопка Отмена, которую пользователи нажимают для закрытия диалогового окна и прекращения дальнейшей работы функции.
Кнопка Закрыть в заголовке окна.
Значок.
Кнопки Свернуть, Развернуть и Восстановить.
Меню Система, чтобы сворачивать, разворачивать, восстанавливать и закрывать диалоговое окно.
Положение выше и в центре окна, которое открывает диалоговое окно.
Возможность изменения размера, где это возможно, чтобы диалоговое окно не было слишком маленьким, и пользователь мог установить полезный размер по умолчанию. Для этого необходимо задать как значения по умолчанию, так и минимальные размеры.
Кнопку ESC следует настроить как сочетание клавиш, которое вызывает нажатие кнопки Отмена. Это делается установкой свойства IsCancel кнопки Отмена в значение
true
.Кнопка ENTER (или RETURN) следует настроить как сочетание клавиш, которое вызывает нажатие кнопки ОК. Это делается установкой свойства IsDefault кнопки OK в значение
true
.
Следующий код демонстрирует такую конфигурацию.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.MarginsDialogBox"
xmlns:local="clr-namespace:SDKSample"
Title="Margins"
Height="190"
Width="300"
MinHeight="10"
MinWidth="300"
ResizeMode="CanResizeWithGrip"
ShowInTaskbar="False"
WindowStartupLocation="CenterOwner"
FocusManager.FocusedElement="{Binding ElementName=leftMarginTextBox}">
<Grid>
<!-- Accept or Cancel -->
<StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="4">
<Button Name="okButton" Click="okButton_Click" IsDefault="True">OK</Button>
<Button Name="cancelButton" IsCancel="True">Cancel</Button>
</StackPanel>
</Grid >
</Window>
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace SDKSample
{
public partial class MarginsDialogBox : Window
{
public MarginsDialogBox()
{
InitializeComponent();
}
}
}
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Input
Namespace SDKSample
Public Class MarginsDialogBox
Inherits Window
Public Sub New()
Me.InitializeComponent()
End Sub
End Class
End Namespace
Пользовательский интерфейс для диалогового окна также распространяется в строку меню окна, открывающего диалоговое окно. Если пункт меню вызывает функцию, которая перед продолжением выполнения требует взаимодействия с пользователем посредством диалогового окна, то в названии этого пункта меню будет многоточие в заголовке, как показано ниже.
<!--Main Window-->
<MenuItem Name="formatMarginsMenuItem" Header="_Margins..." Click="formatMarginsMenuItem_Click" />
Если пункт меню вызывает функцию, которая отображает диалоговое окно, не требующее взаимодействия с пользователем, например диалоговое окно "О программе", многоточие не требуется.
Открытие модального диалогового окна
Диалоговое окно обычно отображается в результате выбора пользователем пункта меню для выполнения доменной функции, такой как установка полей документа в текстовом процессоре. Отображение диалогового окна похоже на отображение обычного окна, хотя требуется дополнительная настройка для диалогового окна. Весь процесс создания, настройки и открытия диалогового окна показан в следующем коде.
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Win32;
namespace SDKSample
{
public partial class MainWindow : Window
{
bool needsToBeSaved;
void formatMarginsMenuItem_Click(object sender, RoutedEventArgs e)
{
// Instantiate the dialog box
MarginsDialogBox dlg = new MarginsDialogBox();
// Configure the dialog box
dlg.Owner = this;
dlg.DocumentMargin = this.documentTextBox.Margin;
// Open the dialog box modally
dlg.ShowDialog();
}
}
}
Imports System.ComponentModel
Imports System.Windows
Imports System.Windows.Controls
Imports Microsoft.Win32
Namespace SDKSample
Public Class MainWindow
Inherits Window
Private Sub formatMarginsMenuItem_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
' Instantiate the dialog box
Dim dlg As New MarginsDialogBox
' Configure the dialog box
dlg.Owner = Me
dlg.DocumentMargin = Me.documentTextBox.Margin
' Open the dialog box modally
dlg.ShowDialog()
End Sub
End Class
End Namespace
Здесь код передает в диалоговое окно сведения по умолчанию (о текущих полях). Кроме того, в коде устанавливается свойство Window.Owner со ссылкой на окно, в котором отображается диалоговое окно. Как правило, всегда следует устанавливать владельца диалогового окна, чтобы задать общее для всех диалоговых окон поведение, связанное с состоянием окна (дополнительные сведения см. в разделе Общие сведения об окнах WPF).
Примечание.
Необходимо задать владельца для поддержки автоматизации пользовательского интерфейса (UI) в диалоговых окнах (см. раздел Обзор автоматизации пользовательского интерфейса).
После настройки диалогового окна оно отображается как модальное путем вызова метода ShowDialog.
Проверка пользовательских данных
Если открывается диалоговое окно и пользователь предоставляет требуемые данные, диалоговое окно отвечает за проверку допустимости предоставленных данных по следующим причинам.
С точки зрения безопасности следует проверять все входные данные.
С точки зрения конкретного домена проверка данных предотвращает обработку в коде ошибочных данных, которые могут вызывать исключения.
С точки зрения взаимодействия с пользователем диалоговое окно может помочь пользователям, показывая, какие введенные ими данные являются недопустимыми.
С точки зрения производительности проверка данных в многоуровневом приложении может уменьшить количество циклов обработки между уровнями клиента и приложения, особенно в том случае, если в приложение входят веб-службы или серверные базы данных.
Чтобы проверить связанный элемент управления в WPF, необходимо определить правило проверки и связать его с привязкой. Правило проверки — это пользовательский класс, производный от ValidationRule. В следующем примере показано правило проверки MarginValidationRule
, которое проверяет, имеет ли привязанное значение тип Double, и находится ли оно в пределах указанного диапазона.
using System.Globalization;
using System.Windows.Controls;
namespace SDKSample
{
public class MarginValidationRule : ValidationRule
{
double minMargin;
double maxMargin;
public double MinMargin
{
get { return this.minMargin; }
set { this.minMargin = value; }
}
public double MaxMargin
{
get { return this.maxMargin; }
set { this.maxMargin = value; }
}
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
double margin;
// Is a number?
if (!double.TryParse((string)value, out margin))
{
return new ValidationResult(false, "Not a number.");
}
// Is in range?
if ((margin < this.minMargin) || (margin > this.maxMargin))
{
string msg = string.Format("Margin must be between {0} and {1}.", this.minMargin, this.maxMargin);
return new ValidationResult(false, msg);
}
// Number is valid
return new ValidationResult(true, null);
}
}
}
Imports System.Globalization
Imports System.Windows.Controls
Namespace SDKSample
Public Class MarginValidationRule
Inherits ValidationRule
Private _maxMargin As Double
Private _minMargin As Double
Public Property MaxMargin() As Double
Get
Return Me._maxMargin
End Get
Set(ByVal value As Double)
Me._maxMargin = value
End Set
End Property
Public Property MinMargin() As Double
Get
Return Me._minMargin
End Get
Set(ByVal value As Double)
Me._minMargin = value
End Set
End Property
Public Overrides Function Validate(ByVal value As Object, ByVal cultureInfo As CultureInfo) As ValidationResult
Dim margin As Double
' Is a number?
If Not Double.TryParse(CStr(value), margin) Then
Return New ValidationResult(False, "Not a number.")
End If
' Is in range?
If ((margin < Me.MinMargin) OrElse (margin > Me.MaxMargin)) Then
Dim msg As String = String.Format("Margin must be between {0} and {1}.", Me.MinMargin, Me.MaxMargin)
Return New ValidationResult(False, msg)
End If
' Number is valid
Return New ValidationResult(True, Nothing)
End Function
End Class
End Namespace
В этом коде логика проверки правила проверки реализована путем переопределения метода Validate, который проверяет данные и возвращает соответствующее значение ValidationResult.
Чтобы сопоставить это правило проверки со связанным элементом управления, используется следующая разметка.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.MarginsDialogBox"
xmlns:local="clr-namespace:SDKSample"
Title="Margins"
Height="190"
Width="300"
MinHeight="10"
MinWidth="300"
ResizeMode="CanResizeWithGrip"
ShowInTaskbar="False"
WindowStartupLocation="CenterOwner"
FocusManager.FocusedElement="{Binding ElementName=leftMarginTextBox}">
<Grid>
<!-- Left Margin -->
<Label Grid.Column="0" Grid.Row="0">Left Margin:</Label>
<TextBox Name="leftMarginTextBox" Grid.Column="1" Grid.Row="0">
<TextBox.Text>
<Binding Path="Left" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<local:MarginValidationRule MinMargin="0" MaxMargin="10" />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
</Grid >
</Window>
После сопоставления правила проверки WPF будет автоматически применять его при вводе данных в связанный элемент управления. Если элемент управления содержит недопустимые данные, WPF отображает красные границы вокруг недопустимого элемента, как показано на следующем рисунке.
WPF не препятствует выходу пользователя из недопустимого элемента управления до ввода правильных данных. Это правильное поведение диалогового окна; пользователь должен иметь возможность свободно перемещаться по элементам управления в диалоговом окне, независимо от того, правильны ли введенные данные. Однако это означает, что пользователь может ввести недопустимые данные и нажать кнопку ОК. По этой причине код также должен проверить все элементы управления в диалоговом окне после нажатия кнопки ОК путем обработки события Click.
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace SDKSample
{
public partial class MarginsDialogBox : Window
{
void okButton_Click(object sender, RoutedEventArgs e)
{
// Don't accept the dialog box if there is invalid data
if (!IsValid(this)) return;
}
// Validate all dependency objects in a window
bool IsValid(DependencyObject node)
{
// Check if dependency object was passed
if (node != null)
{
// Check if dependency object is valid.
// NOTE: Validation.GetHasError works for controls that have validation rules attached
bool isValid = !Validation.GetHasError(node);
if (!isValid)
{
// If the dependency object is invalid, and it can receive the focus,
// set the focus
if (node is IInputElement) Keyboard.Focus((IInputElement)node);
return false;
}
}
// If this dependency object is valid, check all child dependency objects
foreach (object subnode in LogicalTreeHelper.GetChildren(node))
{
if (subnode is DependencyObject)
{
// If a child dependency object is invalid, return false immediately,
// otherwise keep checking
if (IsValid((DependencyObject)subnode) == false) return false;
}
}
// All dependency objects are valid
return true;
}
}
}
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Input
Namespace SDKSample
Public Class MarginsDialogBox
Inherits Window
Private Sub okButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
' Don't accept the dialog box if there is invalid data
If Not Me.IsValid(Me) Then Return
End Sub
' Validate all dependency objects in a window
Private Function IsValid(ByVal node As DependencyObject) As Boolean
' Check if dependency object was passed and if dependency object is valid.
' NOTE: Validation.GetHasError works for controls that have validation rules attached
If ((Not node Is Nothing) AndAlso Validation.GetHasError(node)) Then
' If the dependency object is invalid, and it can receive the focus,
' set the focus
If TypeOf node Is IInputElement Then
Keyboard.Focus(DirectCast(node, IInputElement))
End If
Return False
End If
' If this dependency object is valid, check all child dependency objects
Dim subnode As Object
For Each subnode In LogicalTreeHelper.GetChildren(node)
If (TypeOf subnode Is DependencyObject AndAlso Not Me.IsValid(DirectCast(subnode, DependencyObject))) Then
' If a child dependency object is invalid, return false immediately,
' otherwise keep checking
Return False
End If
Next
' All dependency objects are valid
Return True
End Function
End Class
End Namespace
Этот код перечисляет все объекты зависимости в окне, и если какие-либо объекты недопустимы (согласно возвращенному значению GetHasError), недопустимый элемент управления получает фокус, метод IsValid
возвращает значение false
, и окно считается недопустимым.
Если диалоговое окно является допустимым, оно может быть безопасно закрыто и выполнен возврат. В рамках процесса возврата необходимо возвращать результат в вызывающую функцию.
Установка результата модального диалогового окна
Открытие диалогового окна с помощью ShowDialog принципиально похоже на вызов метода: код, открывший диалоговое окно с помощью ShowDialog, ожидает возврата ShowDialog. При возврате ShowDialog код, который его вызвал, должен решить, продолжить или прекратить обработку, на основе того, какую кнопку нажал пользователь, OK или Отмена. Для облегчения принятия этого решения диалоговое окно должно возвращать выбор пользователя как значение Boolean, возвращенное методом ShowDialog.
При нажатии кнопки OK ShowDialog должен возвращать true
. Это можно сделать путем установки свойства DialogResult диалогового окна, когда нажимается кнопка OK.
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace SDKSample
{
public partial class MarginsDialogBox : Window
{
void okButton_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = true;
}
}
}
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Input
Namespace SDKSample
Public Class MarginsDialogBox
Inherits Window
Private Sub okButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
' Dialog box accepted
MyBase.DialogResult = New Nullable(Of Boolean)(True)
End Sub
End Class
End Namespace
Обратите внимание, что установка этого свойства DialogResult также приводит к автоматическому закрытию окна, что не требует явного вызова Close.
При нажатии кнопки Отмена ShowDialog должен возвращать false
, что также требует установку свойства DialogResult.
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace SDKSample
{
public partial class MarginsDialogBox : Window
{
void cancelButton_Click(object sender, RoutedEventArgs e)
{
// Dialog box canceled
this.DialogResult = false;
}
}
}
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Input
Namespace SDKSample
Public Class MarginsDialogBox
Inherits Window
Private Sub cancelButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
' Dialog box canceled
Me.DialogResult = False
End Sub
End Class
End Namespace
Если свойство IsCancel кнопки установить в значение true
, и пользователь нажимает либо кнопку Отмена или кнопку ESC, параметр DialogResult автоматически устанавливается в значение false
. Следующая разметка действует так же, как предыдущий код, без необходимости обработки события Click.
<Button Name="cancelButton" IsCancel="True">Cancel</Button>
Диалоговое окно автоматически возвращает значение false
, когда пользователь нажимает кнопку Закрыть в заголовке или выбирает пункт меню Закрыть в меню Система.
Обработка данных, возвращенных из модального диалогового окна
Если в диалоговом окне установлено DialogResult, функция, открывшая его, может получить результат диалогового окна, проверив свойство DialogResult, возвращаемое методом ShowDialog.
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Win32;
namespace SDKSample
{
public partial class MainWindow : Window
{
void formatMarginsMenuItem_Click(object sender, RoutedEventArgs e)
{
// Process data entered by user if dialog box is accepted
if (dlg.DialogResult == true)
{
// Update fonts
this.documentTextBox.Margin = dlg.DocumentMargin;
}
}
}
}
Imports System.ComponentModel
Imports System.Windows
Imports System.Windows.Controls
Imports Microsoft.Win32
Namespace SDKSample
Public Class MainWindow
Inherits Window
Private Sub formatMarginsMenuItem_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
' Process data entered by user if dialog box is accepted
If (dlg.DialogResult.GetValueOrDefault = True) Then
Me.documentTextBox.Margin = dlg.DocumentMargin
End If
End Sub
End Class
End Namespace
Если результатом диалогового окна является значение true
, функция использует его в качестве подсказки для получения и обработки данных, предоставленных пользователем.
Примечание.
После возврата ShowDialog повторно открыто диалоговое окно невозможно. Вместо этого придется создать новый экземпляр.
Если результатом диалогового окна является значение false
, функция должна соответствующим образом завершить обработку.
Создание немодального пользовательского диалогового окна
Немодальное диалоговое окно, например диалоговое окно поиска, показанное на следующем рисунке, в основном имеет такой же внешний вид, как и модальное диалоговое окно.
Однако поведение несколько отличается, как показано в следующих разделах.
Открытие немодального диалогового окна
Немодальное диалоговое окно открывается вызовом метода Show.
<!--Main Window-->
<MenuItem Name="editFindMenuItem" Header="_Find" InputGestureText="Ctrl+F" Click="editFindMenuItem_Click" />
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Win32;
namespace SDKSample
{
public partial class MainWindow : Window
{
void editFindMenuItem_Click(object sender, RoutedEventArgs e)
{
// Instantiate the dialog box
FindDialogBox dlg = new FindDialogBox(this.documentTextBox);
// Configure the dialog box
dlg.Owner = this;
dlg.TextFound += new TextFoundEventHandler(dlg_TextFound);
// Open the dialog box modally
dlg.Show();
}
}
}
Imports System.ComponentModel
Imports System.Windows
Imports System.Windows.Controls
Imports Microsoft.Win32
Namespace SDKSample
Public Class MainWindow
Inherits Window
Private Sub editFindMenuItem_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
Dim dlg As New FindDialogBox(Me.documentTextBox)
dlg.Owner = Me
AddHandler dlg.TextFound, New TextFoundEventHandler(AddressOf Me.dlg_TextFound)
dlg.Show()
End Sub
End Class
End Namespace
В отличие от ShowDialog, Show возвращается немедленно. Следовательно, вызывающее окно не может определить, когда немодальное диалоговое окно закрывается, и поэтому не знает, когда следует проверить результат диалогового окна или получить данные из диалогового окна для дальнейшей обработки. Поэтому диалоговому окну необходимо создать альтернативный способ возврата данных в вызывающее окно для обработки.
Обработка данных, возвращенных из немодального диалогового окна
В этом примере FindDialogBox
может возвращать в главное окно один или несколько результатов поиска, в зависимости от искомого текста, без какой-либо определенной частоты. Как и в случае с модальным диалоговым окном, немодальное диалоговое окно может возвращать результаты с помощью свойств. Однако окну, которому принадлежит данное диалоговое окно, нужно знать, когда следует проверять эти свойства. Один из способов сделать это — реализовать для диалогового окна событие, которое возникает всякий раз, когда текст найден. FindDialogBox
реализует для этой цели событие TextFoundEvent
, для чего сначала требуется делегат.
using System;
namespace SDKSample
{
public delegate void TextFoundEventHandler(object sender, EventArgs e);
}
Namespace SDKSample
Public Delegate Sub TextFoundEventHandler(ByVal sender As Object, ByVal e As EventArgs)
End Namespace
Используя делегат TextFoundEventHandler
, FindDialogBox
реализует TextFoundEvent
.
using System;
using System.Windows;
using System.Windows.Controls;
using System.Text.RegularExpressions;
namespace SDKSample
{
public partial class FindDialogBox : Window
{
public event TextFoundEventHandler TextFound;
protected virtual void OnTextFound()
{
TextFoundEventHandler textFound = this.TextFound;
if (textFound != null) textFound(this, EventArgs.Empty);
}
}
}
Imports System.Windows
Imports System.Windows.Controls
Imports System.Text.RegularExpressions
Namespace SDKSample
Public Class FindDialogBox
Inherits Window
Public Event TextFound As TextFoundEventHandler
Protected Overridable Sub OnTextFound()
RaiseEvent TextFound(Me, EventArgs.Empty)
End Sub
End Class
End Namespace
В результате Find
может вызывать событие, когда найден результат поиска.
using System;
using System.Windows;
using System.Windows.Controls;
using System.Text.RegularExpressions;
namespace SDKSample
{
public partial class FindDialogBox : Window
{
void findNextButton_Click(object sender, RoutedEventArgs e)
{
// Text found
this.index = match.Index;
this.length = match.Length;
OnTextFound();
}
}
}
Imports System.Windows
Imports System.Windows.Controls
Imports System.Text.RegularExpressions
Namespace SDKSample
Public Class FindDialogBox
Inherits Window
Me.Index = match.Index
Me.Length = match.Length
RaiseEvent TextFound(Me, EventArgs.Empty)
End Class
End Namespace
Затем окну-владельцу нужно зарегистрировать и обработать это событие.
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Win32;
namespace SDKSample
{
public partial class MainWindow : Window
{
void dlg_TextFound(object sender, EventArgs e)
{
// Get the find dialog box that raised the event
FindDialogBox dlg = (FindDialogBox)sender;
// Get find results and select found text
this.documentTextBox.Select(dlg.Index, dlg.Length);
this.documentTextBox.Focus();
}
}
}
Imports System.ComponentModel
Imports System.Windows
Imports System.Windows.Controls
Imports Microsoft.Win32
Namespace SDKSample
Public Class MainWindow
Inherits Window
Private Sub dlg_TextFound(ByVal sender As Object, ByVal e As EventArgs)
Dim dlg As FindDialogBox = DirectCast(sender, FindDialogBox)
Me.documentTextBox.Select(dlg.Index, dlg.Length)
Me.documentTextBox.Focus()
End Sub
End Class
End Namespace
Закрытие немодального диалогового окна
Поскольку не требуется устанавливать свойство DialogResult, немодальное диалоговое окно можно закрыть с помощью предоставляемых системой механизмов, в том числе следующих.
Нажатие кнопки Закрыть в заголовке окна.
Нажатие клавиш ALT + F4.
Выбор команды Закрыть в меню Система.
Кроме того, ваш код может вызыватьClose при нажатии кнопки Закрыть.
using System;
using System.Windows;
using System.Windows.Controls;
using System.Text.RegularExpressions;
namespace SDKSample
{
public partial class FindDialogBox : Window
{
void closeButton_Click(object sender, RoutedEventArgs e)
{
// Close dialog box
this.Close();
}
}
}
Imports System.Windows
Imports System.Windows.Controls
Imports System.Text.RegularExpressions
Namespace SDKSample
Public Class FindDialogBox
Inherits Window
Private Sub closeButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
MyBase.Close()
End Sub
End Class
End Namespace
См. также
.NET Desktop feedback