Omówienie okien dialogowych

Aplikacje autonomiczne zazwyczaj mają główne okno, w którym są wyświetlane główne dane, na których działa aplikacja, i uwidacznia funkcje przetwarzania tych danych za pomocą mechanizmów interfejsu użytkownika, takich jak paski menu, paski narzędzi i paski stanu. Aplikacja nietrywialna może również wyświetlać dodatkowe okna, aby wykonać następujące czynności:

  • Wyświetl określone informacje dla użytkowników.

  • Zbieranie informacji od użytkowników.

  • Wyświetlaj i zbieraj informacje.

Te typy okien są znane jako okna dialogowe i istnieją dwa typy: modalne i moderowane.

Modalne okno dialogowe jest wyświetlane przez funkcję, gdy funkcja potrzebuje dodatkowych danych od użytkownika, aby kontynuować. Ponieważ funkcja zależy od modalnego okna dialogowego do zbierania danych, modalne okno dialogowe uniemożliwia również użytkownikowi aktywowanie innych okien w aplikacji, gdy pozostaje otwarty. W większości przypadków modalne okno dialogowe umożliwia użytkownikowi sygnał po zakończeniu pracy z modalnym oknem dialogowym, naciskając przycisk OK lub Anuluj . Naciśnięcie przycisku OK oznacza, że użytkownik wprowadził dane i chce, aby funkcja kontynuowała przetwarzanie tych danych. Naciśnięcie przycisku Anuluj oznacza, że użytkownik chce całkowicie zatrzymać wykonywanie funkcji. Najpopularniejsze przykłady modalnych okien dialogowych są wyświetlane w celu otwierania, zapisywania i drukowania danych.

Z drugiej strony okno dialogowe bez moderowania nie uniemożliwia użytkownikowi aktywowania innych okien podczas jego otwierania. Jeśli na przykład użytkownik chce znaleźć wystąpienia określonego słowa w dokumencie, okno główne często otwiera okno dialogowe, aby zapytać użytkownika, jakiego słowa szuka. Ponieważ znalezienie wyrazu nie uniemożliwia użytkownikowi edytowania dokumentu, jednak okno dialogowe nie musi być modalne. Modeless okno dialogowe zawiera przynajmniej przycisk Zamknij , aby zamknąć okno dialogowe i może udostępnić dodatkowe przyciski do wykonywania określonych funkcji, takich jak przycisk Znajdź dalej , aby znaleźć następne słowo zgodne z kryteriami wyszukiwania wyrazów.

Program Windows Presentation Foundation (WPF) umożliwia tworzenie kilku typów okien dialogowych, w tym okien komunikatów, typowych okien dialogowych i niestandardowych okien dialogowych. W tym temacie omówiono poszczególne elementy, a przykład okna dialogowego zawiera pasujące przykłady.

Pola wiadomości

Okno dialogowe to okno dialogowe, którego można użyć do wyświetlania informacji tekstowych i umożliwienia użytkownikom podejmowania decyzji za pomocą przycisków. Na poniższej ilustracji przedstawiono pole komunikatu, które wyświetla informacje tekstowe, zadaje pytanie i udostępnia użytkownikowi trzy przyciski umożliwiające udzielenie odpowiedzi na pytanie.

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

Aby utworzyć pole komunikatu MessageBox , należy użyć klasy . MessageBox Umożliwia skonfigurowanie tekstu pola wiadomości, tytułu, ikony i przycisków przy użyciu kodu, takiego jak poniżej.

// 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

Aby wyświetlić okno komunikatu, wywołasz metodę staticShow , jak pokazano w poniższym kodzie.

// Display message box
MessageBox.Show(messageBoxText, caption, button, icon);
' Display message box
MessageBox.Show(messageBoxText, caption, button, icon)

Gdy kod pokazujący okno komunikatu musi wykryć i przetworzyć decyzję użytkownika (który przycisk został naciśnięty), kod może sprawdzić wynik pola komunikatu, jak pokazano w poniższym kodzie.

// 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

Aby uzyskać więcej informacji na temat używania pól komunikatów, zobacz MessageBoxPrzykład , MessageBox Sample i Dialog Box Sample.

Chociaż MessageBox może oferować proste środowisko użytkownika okna dialogowego, zaletą jest MessageBox to, że jest to jedyny typ okna, który może być wyświetlany przez aplikacje uruchamiane w piaskownicy zabezpieczeń częściowych zaufania (zobacz Zabezpieczenia), takich jak aplikacje przeglądarki XAML (XBAPs).

Większość okien dialogowych wyświetla i zbiera bardziej złożone dane niż wynik okna komunikatu, w tym tekst, zaznaczenie (pola wyboru), wzajemnie wykluczające się zaznaczenie (przyciski radiowe) i wybór listy (pola listy, pola kombi, pola listy rozwijanej). W tym przypadku program Windows Presentation Foundation (WPF) udostępnia kilka typowych okien dialogowych i umożliwia tworzenie własnych okien dialogowych, chociaż korzystanie z nich jest ograniczone do aplikacji działających z pełnym zaufaniem.

Typowe okna dialogowe

System Windows implementuje różne okna dialogowe wielokrotnego użytku, które są wspólne dla wszystkich aplikacji, w tym okna dialogowe do otwierania plików, zapisywania plików i drukowania. Ponieważ te okna dialogowe są implementowane przez system operacyjny, mogą być współużytkowane przez wszystkie aplikacje działające w systemie operacyjnym, co pomaga w spójności środowiska użytkownika; gdy użytkownicy znają korzystanie z okna dialogowego dostarczonego przez system operacyjny w jednej aplikacji, nie muszą nauczyć się używać tego okna dialogowego w innych aplikacjach. Ponieważ te okna dialogowe są dostępne dla wszystkich aplikacji i ponieważ pomagają zapewnić spójne środowisko użytkownika, są one znane jako typowe okna dialogowe.

Program Windows Presentation Foundation (WPF) hermetyzuje otwarty plik, zapisz plik i wyświetla typowe okna dialogowe oraz udostępnia je jako klasy zarządzane do użycia w aplikacjach autonomicznych. Ten temat zawiera krótkie omówienie każdego z nich.

Okno dialogowe Otwieranie pliku

Otwarte okno dialogowe pliku, pokazane na poniższym rysunku, jest używane przez funkcję otwierania pliku w celu pobrania nazwy pliku do otwarcia.

An Open dialog box showing the location to retrieve the file.

Typowe otwarte okno dialogowe pliku jest implementowane jako OpenFileDialog klasa i znajduje się w Microsoft.Win32 przestrzeni nazw. Poniższy kod pokazuje, jak utworzyć, skonfigurować i pokazać jeden oraz jak przetworzyć wynik.

// 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

Aby uzyskać więcej informacji na temat okna dialogowego otwierania pliku, zobacz Microsoft.Win32.OpenFileDialog.

Uwaga

OpenFileDialog można używać do bezpiecznego pobierania nazw plików przez aplikacje działające z częściowym zaufaniem (zobacz Zabezpieczenia).

Zapisz Plik — Okno dialogowe

Okno dialogowe zapisywanie pliku, pokazane na poniższym rysunku, jest używane przez funkcję zapisywania plików w celu pobrania nazwy pliku do zapisania.

A Save As dialog box showing the location to save the file.

Typowe okno dialogowe zapisywania pliku jest implementowane jako SaveFileDialog klasa i znajduje się w Microsoft.Win32 przestrzeni nazw. Poniższy kod pokazuje, jak utworzyć, skonfigurować i pokazać jeden oraz jak przetworzyć wynik.

// 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

Aby uzyskać więcej informacji na temat okna dialogowego zapisywania pliku, zobacz Microsoft.Win32.SaveFileDialog.

Okno dialogowe drukowania, pokazane na poniższym rysunku, jest używane przez funkcję drukowania do wybierania i konfigurowania drukarki, do którego użytkownik chce drukować dane.

Screenshot that shows a Print dialog box.

Wspólne okno dialogowe drukowania jest implementowane jako PrintDialog klasa i znajduje się w System.Windows.Controls przestrzeni nazw. Poniższy kod pokazuje, jak utworzyć, skonfigurować i pokazać go.

// 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

Aby uzyskać więcej informacji na temat okna dialogowego drukowania, zobacz System.Windows.Controls.PrintDialog. Szczegółowe omówienie drukowania w WPF można znaleźć w temacie Drukowanie — omówienie.

Niestandardowe okna dialogowe

Chociaż typowe okna dialogowe są przydatne i powinny być używane w miarę możliwości, nie obsługują one wymagań dotyczących okien dialogowych specyficznych dla domeny. W takich przypadkach należy utworzyć własne okna dialogowe. Jak zobaczymy, okno dialogowe jest oknem ze specjalnymi zachowaniami. Window implementuje te zachowania i w związku z tym służy Window do tworzenia niestandardowych modalnych i moderacyjnych okien dialogowych.

Tworzenie modalnego okna dialogowego niestandardowego

W tym temacie pokazano, jak utworzyć Window typową implementację modalnego okna dialogowego przy użyciu okna dialogowego jako przykładu Margins (zobacz Przykład okna dialogowego). Okno Margins dialogowe jest wyświetlane na poniższej ilustracji.

A Margins dialog box with fields to define left margin, top margin, right margin, and bottom margin.

Konfigurowanie modalnego okna dialogowego

Interfejs użytkownika typowego okna dialogowego zawiera następujące elementy:

  • Różne kontrolki wymagane do zebrania żądanych danych.

  • Przycisk OK , który użytkownicy klikają, aby zamknąć okno dialogowe, powrócić do funkcji i kontynuować przetwarzanie.

  • Przycisk Anuluj , który użytkownicy klikają, aby zamknąć okno dialogowe i zatrzymać funkcję w dalszym przetwarzaniu.

  • Przycisk Zamknij na pasku tytułu.

  • Ikona.

  • Przyciski Minimalizuj, Maksymalizuj i Przywróć.

  • Menu System , aby zminimalizować, zmaksymalizować, przywrócić i zamknąć okno dialogowe.

  • Pozycja powyżej i w środku okna, które otworzyło okno dialogowe.

  • Możliwość zmiany rozmiaru, jeśli jest to możliwe, aby zapobiec zbyt małej wielkości okna dialogowego i udostępnić użytkownikowi przydatny rozmiar domyślny. Wymaga to ustawienia zarówno domyślnych, jak i minimalnych wymiarów.

  • Klawisz ESC jako skrót klawiaturowy, który powoduje naciśnięcie przycisku Anuluj . W tym celu należy ustawić IsCancel właściwość przycisku Anuluj na truewartość .

  • Klawisz ENTER (lub RETURN) jako skrót klawiaturowy, który powoduje naciśnięcie przycisku OK . W tym celu należy ustawić IsDefault właściwość przycisku trueOK .

Poniższy kod demonstruje tę konfigurację.

<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

Środowisko użytkownika okna dialogowego rozszerza się również na pasek menu okna, które otwiera okno dialogowe. Gdy element menu uruchamia funkcję, która wymaga interakcji użytkownika za pośrednictwem okna dialogowego, zanim funkcja będzie mogła kontynuować, element menu dla funkcji będzie miał wielokropek w nagłówku, jak pokazano tutaj.

<!--Main Window-->
<MenuItem Name="formatMarginsMenuItem" Header="_Margins..." Click="formatMarginsMenuItem_Click" />

Gdy element menu uruchamia funkcję wyświetlającą okno dialogowe, które nie wymaga interakcji użytkownika, na przykład okno dialogowe Informacje, wielokropek nie jest wymagany.

Otwieranie modalnego okna dialogowego

Okno dialogowe jest zwykle wyświetlane w wyniku wybrania elementu menu w celu wykonania funkcji specyficznej dla domeny, na przykład ustawienia marginesów dokumentu w edytorze tekstów. Wyświetlanie okna jako okna dialogowego jest podobne do wyświetlania normalnego okna, chociaż wymaga dodatkowej konfiguracji specyficznej dla okna dialogowego. Cały proces tworzenia wystąpienia, konfigurowania i otwierania okna dialogowego jest wyświetlany w poniższym kodzie.

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

W tym miejscu kod przekazuje informacje domyślne (bieżące marginesy) do okna dialogowego. Ustawia Window.Owner również właściwość z odwołaniem do okna, w którym jest wyświetlane okno dialogowe. Ogólnie rzecz biorąc, należy zawsze ustawić właściciela okna dialogowego, aby zapewnić zachowania związane ze stanem okna, które są wspólne dla wszystkich okien dialogowych (zobacz WPF Windows Overview , aby uzyskać więcej informacji).

Uwaga

Musisz podać właściciela, aby obsługiwał automatyzację interfejsu użytkownika dla okien dialogowych (zobacz automatyzacja interfejsu użytkownika Omówienie).

Po skonfigurowaniu okna dialogowego jest wyświetlany modalnie przez wywołanie ShowDialog metody .

Weryfikowanie danych dostarczonych przez użytkownika

Gdy zostanie otwarte okno dialogowe i użytkownik dostarczy wymagane dane, okno dialogowe jest odpowiedzialne za zapewnienie, że podane dane są prawidłowe z następujących powodów:

  • Z punktu widzenia zabezpieczeń wszystkie dane wejściowe powinny być weryfikowane.

  • Z perspektywy specyficznej dla domeny weryfikacja danych uniemożliwia przetwarzanie przez kod błędnych danych, co może potencjalnie zgłaszać wyjątki.

  • Z perspektywy środowiska użytkownika okno dialogowe może pomóc użytkownikom, pokazując im, które wprowadzone dane są nieprawidłowe.

  • Z punktu widzenia wydajności walidacja danych w aplikacji wielowarstwowej może zmniejszyć liczbę rund między klientem a warstwami aplikacji, szczególnie gdy aplikacja składa się z usług sieci Web lub baz danych opartych na serwerze.

Aby zweryfikować powiązaną kontrolkę w WPF, należy zdefiniować regułę weryfikacji i skojarzyć ją z powiązaniem. Reguła sprawdzania poprawności to klasa niestandardowa, która pochodzi z klasy ValidationRule. W poniższym przykładzie przedstawiono regułę sprawdzania poprawności , która sprawdza, MarginValidationRuleczy wartość powiązana jest wartością Double i znajduje się w określonym zakresie.

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

W tym kodzie logika walidacji reguły walidacji jest implementowana przez Validate zastąpienie metody, która weryfikuje dane i zwraca odpowiedni ValidationResultelement .

Aby skojarzyć regułę walidacji z powiązaną kontrolką, użyj następującego znacznika.

<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>

Po skojarzeniu reguły sprawdzania poprawności platforma WPF automatycznie zastosuje ją po wprowadzeniu danych do powiązanej kontrolki. Jeśli kontrolka zawiera nieprawidłowe dane, WPF wyświetli czerwone obramowanie wokół nieprawidłowej kontrolki, jak pokazano na poniższym rysunku.

A Margins dialog box with a red border around the invalid left margin value.

WPF nie ogranicza użytkownika do nieprawidłowej kontrolki do momentu wprowadzenia prawidłowych danych. Jest to dobre zachowanie dla okna dialogowego; użytkownik powinien mieć możliwość swobodnego nawigowania po kontrolkach w oknie dialogowym bez względu na to, czy dane są prawidłowe. Oznacza to jednak, że użytkownik może wprowadzić nieprawidłowe dane i nacisnąć przycisk OK . Z tego powodu kod musi również zweryfikować wszystkie kontrolki w oknie dialogowym po naciśnięciu Click przycisku OK przez obsługę zdarzenia.

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

Ten kod wylicza wszystkie obiekty zależności w oknie i, jeśli istnieją nieprawidłowe (jak zwracana przez GetHasError, nieprawidłowa kontrolka pobiera fokus, IsValid metoda zwraca falsewartość , a okno jest uznawane za nieprawidłowe.

Gdy okno dialogowe jest prawidłowe, można bezpiecznie zamknąć i powrócić. W ramach procesu zwracania musi zwrócić wynik do funkcji wywołującej.

Ustawianie wyniku modalnego okna dialogowego

Otwieranie okna dialogowego przy użyciu ShowDialog metody jest zasadniczo podobne do wywoływania metody: kod, który otworzył okno dialogowe przy użyciu ShowDialog oczekiwania do ShowDialog powrotu. Po ShowDialog powrocie kod, który go nazwał, musi zdecydować, czy kontynuować przetwarzanie, czy zatrzymać przetwarzanie, na podstawie tego, czy użytkownik nacisnął przycisk OK , czy przycisk Anuluj . Aby ułatwić tę decyzję, okno dialogowe musi zwrócić wybór użytkownika jako Boolean wartość zwracaną z ShowDialog metody .

Po kliknięciu ShowDialog przycisku OK powinna zostać zwrócona wartość true. Jest to osiągane przez ustawienie DialogResult właściwości okna dialogowego po kliknięciu przycisku 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

Należy pamiętać, że ustawienie DialogResult właściwości powoduje również automatyczne zamknięcie okna, co pozwala złagodzić konieczność jawnego wywołania metody Close.

Po kliknięciu ShowDialog przycisku Anuluj powinien zostać zwrócony element false, który również wymaga ustawienia DialogResult właściwości .

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

Gdy właściwość przycisku jest ustawiona IsCancel na true , a użytkownik naciska przycisk Anuluj lub klawisz ESC, DialogResult jest automatycznie ustawiany na falsewartość . Poniższy znacznik ma taki sam efekt jak poprzedni kod bez konieczności obsługi Click zdarzenia.

<Button Name="cancelButton" IsCancel="True">Cancel</Button>

Okno dialogowe jest automatycznie zwracane false , gdy użytkownik naciska przycisk Zamknij na pasku tytułu lub wybiera element menu Zamknij z menu System .

Przetwarzanie danych zwracanych z modalnego okna dialogowego

Gdy DialogResult jest ustawiana przez okno dialogowe, funkcja, która ją otworzyła, może uzyskać wynik okna dialogowego, sprawdzając właściwość po ShowDialog powrocieDialogResult.

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

Jeśli wynikiem okna dialogowego jest true, funkcja używa tej funkcji jako wskazówek do pobrania i przetworzenia danych dostarczonych przez użytkownika.

Uwaga

Po ShowDialog powrocie nie można ponownie otworzyć okna dialogowego. Zamiast tego należy utworzyć nowe wystąpienie.

Jeśli wynik okna dialogowego to false, funkcja powinna odpowiednio zakończyć przetwarzanie.

Tworzenie niestandardowego okna dialogowego bez moderowania

Okno dialogowe bez moderowania, takie jak okno dialogowe Znajdowanie pokazane na poniższej ilustracji, ma taki sam podstawowy wygląd jak modalne okno dialogowe.

Screenshot that shows a Find dialog box.

Jednak zachowanie jest nieco inne, jak opisano w poniższych sekcjach.

Otwieranie okna dialogowego bez moderowania

Okno dialogowe bez moderowania jest otwierane przez wywołanie Show metody .

<!--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

W przeciwieństwie do ShowDialogmetody funkcja Show zwraca natychmiast. W związku z tym okno wywołujące nie może powiedzieć, kiedy okno dialogowe bez moderowania jest zamknięte i dlatego nie wie, kiedy sprawdzić wynik okna dialogowego lub pobrać dane z okna dialogowego w celu dalszego przetwarzania. Zamiast tego okno dialogowe musi utworzyć alternatywny sposób zwracania danych do okna wywołującego do przetwarzania.

Przetwarzanie danych zwracanych z okna dialogowego bez moderowania

W tym przykładzie FindDialogBox element może zwrócić jeden lub więcej wyników wyszukiwania do okna głównego, w zależności od wyszukiwanego tekstu bez określonej częstotliwości. Podobnie jak w przypadku modalnego okna dialogowego, moderowe okno dialogowe może zwracać wyniki przy użyciu właściwości. Jednak okno, które jest właścicielem okna dialogowego, musi wiedzieć, kiedy sprawdzić te właściwości. Jednym ze sposobów włączenia tego jest zaimplementowanie zdarzenia wywoływanego za każdym razem, gdy zostanie znaleziony tekst. FindDialogBox implementuje element TextFoundEvent w tym celu, który najpierw wymaga delegata.

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

Za pomocą delegata TextFoundEventHandlerFindDialogBox implementuje element 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 W związku z tym może zgłosić zdarzenie po znalezieniu wyniku wyszukiwania.

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

Okno właściciela musi następnie zarejestrować się i obsłużyć to zdarzenie.

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

Zamykanie okna dialogowego bez moderowania

Ponieważ DialogResult nie trzeba ustawiać, można zamknąć bez moderowania okno dialogowe przy użyciu systemu zapewnia mechanizmy, w tym następujące:

  • Kliknięcie przycisku Zamknij na pasku tytułu.

  • Naciśnij klawisze ALT+F4.

  • Wybierz pozycję Zamknij z menu System .

Możesz też wywołać Close kod po kliknięciu przycisku Zamknij .

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

Zobacz też