Общие сведения о диалоговых окнах (.NET в WPF)

Windows Presentation Foundation (WPF) позволяет разрабатывать собственные диалоговые окна. Диалоговые окна — это окна, в которых реализовано определенное намерение и пользовательский интерфейс. В этой статье объясняется, как работает диалоговое окно, а также какие типы диалоговых окон можно создавать и использовать. Диалоговые окна используются для выполнения следующих задач:

  • отображения определенных сведений для пользователей;
  • сбора сведений от пользователей;
  • сбора и отображения сведений.
  • отображения запроса операционной системы, например окна печати;
  • выбора файла или папки.

Окна таких типов называются диалоговыми окнами. Диалоговое окно может отображаться двумя способами: как модальное и как немодальное.

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

Если открыто немодальное диалоговое окно, пользователь может активировать и другие окна. Например, если пользователь хочет найти вхождения конкретного слова в документе, в главном окне часто открывается диалоговое окно с запросом слова для поиска. Так как приложению не требуется запрещать пользователю редактировать документ, диалоговое окно не обязательно должно быть модальным. В немодальном диалоговом окне должна быть как минимум кнопка Закрыть, чтобы можно было закрыть его. Для выполнения определенных функций могут предоставляться другие кнопки, такие как кнопка Найти далее, позволяющее найти следующее слово при поиске слов.

С помощью WPF вы можете создавать разные типы диалоговых окон, такие как окна сообщений, общие диалоговые окна и пользовательские диалоговые окна. В этой статье рассматриваются все эти типы, а в разделе Пример диалогового окна приводятся соответствующие примеры.

Поля сообщения

Окно сообщения — это диалоговое окно, в котором можно отображать текстовую информацию и разрешать пользователям принимать решения с помощью кнопок. На следующем рисунке показано окно сообщения, в котором задается вопрос и предоставляются три кнопки для ответа на этот вопрос.

Word processor dialog box asking if you want to save the changes to the document before the application closes.

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

Дополнительные сведения см. в разделе Открытие окна сообщения.

Общие диалоговые окна

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

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

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

Open file dialog box called from WPF.

Дополнительные сведения об общих диалоговых окнах см. в следующих статьях:

Пользовательские диалоговые окна

Хотя общие диалоговые окна полезны и должны использоваться, когда это возможно, они не соответствуют требованиям к предметно-ориентированным диалоговым окнам. В этих случаях необходимо создавать собственные диалоговые окна. Как мы увидим, диалоговое окно является окном со специальным поведением. В Window реализованы эти типы поведения. С помощью класса Window вы можете создавать модальные и немодальные диалоговые окна.

Если вы создаете собственное диалоговое окно, нужно учитывать множество рекомендаций по разработке. Хотя между окном приложения и диалоговым окном есть сходство, например они совместно используют один базовый класс, диалоговое окно используется только для определенной цели. Обычно диалоговое окно требуется, когда нужно запросить у пользователя определенную информацию или ответ. Как правило, приложение приостанавливает работу во время отображения диалогового окна (модального) с ограничением доступа к остальной части приложения. После закрытия диалогового окна приложение продолжает работу. Но ограничение взаимодействия только диалоговым окном не является обязательным.

После закрытия окна WPF открыть его повторно нельзя. Настраиваемые диалоговые окна — это окна WPF. К ним применяются те же правила. Чтобы узнать, как закрыть окно, см. статью Как закрыть окно или диалоговое окно.

Реализация диалогового окна

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

❌ НЕ СЛЕДУЕТ загромождать диалоговое окно. Интерфейс диалогового окно предназначен для ввода определенных данных или выбора.

✔️ СЛЕДУЕТ реализовать кнопку ОК, позволяющую закрыть окно.

✔️ СЛЕДУЕТ задать для свойства IsDefault кнопки ОК значение true, чтобы пользователь мог нажать клавишу ВВОД для подтверждения и закрытия окна.

✔ РЕКОМЕНДУЕТСЯ добавить кнопку Отмена, чтобы пользователь смог закрыть окно и указать, что он не хочет продолжать взаимодействие с ним.

✔️ СЛЕДУЕТ задать для свойства IsCancel кнопки Отмена значение true, чтобы пользователь мог нажать клавишу ESC для закрытия окна.

✔️ СЛЕДУЕТ задать заголовок окна, чтобы точно указать, что представляет диалоговое окно или что должен делать с ним пользователь.

✔ СЛЕДУЕТ задать минимальные значения ширины и высоты для окна, чтобы пользователь не сделал размер окна слишком маленьким.

✔ РЕКОМЕНДУЕТСЯ отключить возможность изменения размера окна, если для ShowInTaskbar задано значение false. Изменение размера можно отключить, задав для параметра ResizeMode значение NoResize.

Следующий код демонстрирует такую конфигурацию.

<Window x:Class="Dialogs.Margins"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Change Margins"
        Closing="Window_Closing"
        MinHeight="200"
        MinWidth="300"
        SizeToContent="WidthAndHeight"
        ResizeMode="NoResize"
        ShowInTaskbar="False"
        WindowStartupLocation="CenterOwner" 
        FocusManager.FocusedElement="{Binding ElementName=leftMarginTextBox}">
    <Grid Margin="10">
        <Grid.Resources>
            <!-- Default settings for controls -->
            <Style TargetType="{x:Type Label}">
                <Setter Property="Margin" Value="0,3,5,5" />
                <Setter Property="Padding" Value="0,0,0,5" />
            </Style>
            <Style TargetType="{x:Type TextBox}">
                <Setter Property="Margin" Value="0,0,0,5" />
            </Style>
            <Style TargetType="{x:Type Button}">
                <Setter Property="Width" Value="70" />
                <Setter Property="Height" Value="25" />
                <Setter Property="Margin" Value="5,0,0,0" />
            </Style>
        </Grid.Resources>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition />
        </Grid.RowDefinitions>

        <!-- Left,Top,Right,Bottom margins-->
        <Label Grid.Column="0" Grid.Row="0">Left Margin:</Label>
        <TextBox Name="leftMarginTextBox" Grid.Column="1" Grid.Row="0" />

        <Label Grid.Column="0" Grid.Row="1">Top Margin:</Label>
        <TextBox Name="topMarginTextBox" Grid.Column="1" Grid.Row="1"/>

        <Label Grid.Column="0" Grid.Row="2">Right Margin:</Label>
        <TextBox Name="rightMarginTextBox" Grid.Column="1" Grid.Row="2" />

        <Label Grid.Column="0" Grid.Row="3">Bottom Margin:</Label>
        <TextBox Name="bottomMarginTextBox" Grid.Column="1" Grid.Row="3" />

        <!-- Accept or Cancel -->
        <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="4" Orientation="Horizontal" HorizontalAlignment="Right">
            <Button Name="okButton" Click="okButton_Click" IsDefault="True">OK</Button>
            <Button Name="cancelButton" IsCancel="True">Cancel</Button>
        </StackPanel>
    </Grid >
</Window>

Приведенный выше код XAML позволяет создать примерно такое окно:

A dialog box window for WPF that shows left, top, right, bottom text boxes.

Элементы пользовательского интерфейса для открытия диалогового окна

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

<MenuItem Header="_Margins..." Click="formatMarginsMenuItem_Click" />
<!-- or -->
<Button Content="_Margins..." Click="formatMarginsButton_Click" />

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

Пункты меню — это распространенный способ предоставить пользователям возможность работы с действиями приложения, сгруппированными по связанным темам. Вероятно, вы видели меню Файл во многих приложениях. В обычном приложении пункт меню Файл позволяет сохранить, загрузить и распечатать файл. Если после действия будет отображаться модальное окно, заголовок обычно содержит многоточие, как показано на следующем изображении:

A WPF window that shows menu items with an ellipsis to indicate which item shows a dialog box.

В двух пунктах меню есть многоточие: .... Это указывает пользователю, что при выборе этих пунктов меню отображается модальное окно, приостанавливающее работу приложения до тех пор, пока пользователь не закроет его.

Такой метод разработки — это простой способ сообщить пользователю, какого поведения следует ожидать.

Пуговицы

Вы можете следовать принципу, который описан в разделе Пункты меню. Используйте многоточие в тексте кнопки, чтобы указать пользователю, что при ее нажатии появится модальное диалоговое окно. На следующем изображении есть две кнопки, и легко понять, при нажатии какой кнопки отображается диалоговое окно:

A WPF window that shows buttons with an ellipsis to indicate which item shows a dialog box.

возврат результата.

Открытие другого окна (особенно модального) — отличный способ возврата сведений о состоянии и другой информации в ответ на вызывающий код.

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

При нажатии кнопки ОК метод ShowDialog должен возвращать значение true, а при нажатии кнопки Отмена должно возвращаться значение false. Чтобы реализовать такое поведение, задается свойство DialogResult при нажатии кнопки.

private void okButton_Click(object sender, RoutedEventArgs e) =>
    DialogResult = true;

private void cancelButton_Click(object sender, RoutedEventArgs e) =>
    DialogResult = false;
Private Sub okButton_Click(sender As Object, e As RoutedEventArgs)
    DialogResult = True
End Sub

Private Sub cancelButton_Click(sender As Object, e As RoutedEventArgs)
    DialogResult = False
End Sub

Свойство DialogResult можно задать, только если диалоговое окно отображалось с использованиемShowDialog(). Если задано свойство DialogResult, диалоговое окно закрывается.

Если для свойства кнопки IsCancel задано значение true и окно открыто с использованием ShowDialog(), при нажатии клавиши ESC окно закроется и для DialogResult будет установлено значение false.

Дополнительные сведения см. в статье Как закрыть окно или диалоговое окно.

Обработка ответа

ShowDialog() возвращает логическое значение, определяющее поведение пользователя: подтверждение запроса, отображаемого в диалоговом окне, или его отмена. Если вы оповещаете пользователя о чем-то, но от него не требуется принятие решения или предоставление данных, вы можете игнорировать ответ. Кроме того, ответ также можно проверить, просмотрев свойство DialogResult. В следующем коде показано, как обработать ответ:

var dialog = new Margins();

// Display the dialog box and read the response
bool? result = dialog.ShowDialog();

if (result == true)
{
    // User accepted the dialog box
    MessageBox.Show("Your request will be processed.");
}
else
{
    // User cancelled the dialog box
    MessageBox.Show("Sorry it didn't work out, we'll try again later.");
}
Dim marginsWindow As New Margins

Dim result As Boolean? = marginsWindow.ShowDialog()

If result = True Then
    ' User accepted the dialog box
    MessageBox.Show("Your request will be processed.")
Else
    ' User cancelled the dialog box
    MessageBox.Show("Sorry it didn't work out, we'll try again later.")
End If

marginsWindow.Show()

Немодальное диалоговое окно

Чтобы отобразить немодальное диалоговое окно, вызовите Show(). В диалоговом окне должна быть как минимум кнопка Закрыть. Можно предоставить другие кнопки и интерактивные элементы для выполнения определенной функции, например кнопку Найти следующее, чтобы найти следующее слово при выполнении поиска слов.

Так как немодальное диалоговое окно не блокирует работу вызывающего кода, необходимо обеспечить другой способ возврата результата. Выполните одно из следующих действий:

  • предоставление в окне свойства объекта данных;
  • обработка события Window.Closed в вызывающем коде;
  • создание в окне событий, которые возникают, когда пользователь выбирает объект или нажимает определенную кнопку.

В следующем примере с помощью события Window.Closed для пользователя отображается поле сообщения при закрытии диалогового окна. Отображаемое сообщение ссылается на свойство закрытого диалогового окна. Дополнительные сведения см. в статье Как закрыть окно или диалоговое окно.

var marginsWindow = new Margins();

marginsWindow.Closed += (sender, eventArgs) =>
{
    MessageBox.Show($"You closed the margins window! It had the title of {marginsWindow.Title}");
};

marginsWindow.Show();
Dim marginsWindow As New Margins

AddHandler marginsWindow.Closed, Sub(sender As Object, e As EventArgs)
                                     MessageBox.Show($"You closed the margins window! It had the title of {marginsWindow.Title}")
                                 End Sub

marginsWindow.Show()

См. также