Übersicht über Dialogfelder

Eigenständige Anwendungen haben in der Regel ein Hauptfenster, das sowohl die Nutzdaten anzeigt, mit denen die Anwendung arbeitet, als auch die Funktionen zum Verarbeiten dieser Daten über UI-Mechanismen (User Interface, Benutzeroberfläche) wie Menüleisten, Symbolleisten und Statusleisten verfügbar macht. Eine nicht triviale Anwendung kann auch zusätzliche Fenster anzeigen, um Folgendes auszuführen:

  • Spezifische Informationen für Benutzer anzeigen.

  • Informationen von Benutzern erfassen.

  • Informationen sowohl anzeigen als auch erfassen.

Diese Fenstertypen werden als Dialogfelder bezeichnet, von denen es zwei Arten gibt: modale und nicht modale Dialogfelder.

Ein modales Dialogfeld wird von einer Funktion angezeigt, wenn die Funktion zusätzliche Daten von einem Benutzer benötigt, um den Vorgang fortsetzen zu können. Da die Funktion beim Erfassen der Daten vom modalen Dialogfeld abhängig ist, verhindert das modale Dialogfeld auch, dass der Benutzer andere Fenster in der Anwendung aktiviert, während das Dialogfeld geöffnet bleibt. In den meisten Fällen kann ein Benutzer in einem modalen Dialogfeld angeben, wann er es nicht mehr benötigt, indem er auf die Schaltfläche OK oder auf Abbrechen klickt. Durch einen Klick auf die Schaltfläche OK wird angezeigt, dass ein Benutzer Daten eingegeben hat und möchte, dass die Funktion mit der Verarbeitung dieser Daten fortfährt. Durch einen Klick auf die Schaltfläche Abbrechen wird angezeigt, dass ein Benutzer möchte, dass die Funktion die Ausführung komplett abbricht. Die häufigsten Beispiele für modale Dialogfelder sind das Öffnen, Speichern und Drucken von Daten.

Ein nicht modales Dialogfeld hingegen verhindert nicht, dass ein Benutzer andere Fenster aktiviert, so lange es geöffnet ist. Wenn ein Benutzer z. B. Vorkommen eines bestimmten Worts in einem Dokument finden möchte, wird in einem Hauptfenster oft ein Dialogfeld geöffnet, um den Benutzer zu fragen, nach welchem Wort er sucht. Da die Suche nach einem Wort einen Benutzer aber nicht an der Bearbeitung des Dokuments hindert, muss das Dialogfeld nicht unbedingt modal sein. Ein nicht modales Dialogfeld enthält mindestens die Schaltfläche Schließen, um das Dialogfeld zu schließen, und kann weitere Schaltflächen enthalten, um bestimmte Funktionen auszuführen, etwa die Schaltfläche Weitersuchen, um das nächste Wort zu suchen, das den Suchkriterien einer Wortsuche entspricht.

Mit WPF (Windows Presentation Foundation) können Sie mehrere Typen von Dialogfeldern erstellen. Dazu zählen Meldungsfelder, Standarddialogfelder und benutzerdefinierte Dialogfelder. In diesem Thema wird jeder Typ erläutert, und das Dialogfeldbeispiel stellt entsprechende Beispiele bereit.

Meldungsfelder

Ein Meldungsfeld ist ein Dialogfeld, mit dem Textinformationen angezeigt werden können und mit dem Benutzer mithilfe von Schaltflächen Entscheidungen treffen können. In der folgenden Abbildung ist ein Meldungsfeld dargestellt, in dem Textinformationen angezeigt werden, eine Frage gestellt wird und der Benutzer mithilfe von drei Schaltflächen die Frage beantworten kann.

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

Um ein Meldungsfeld zu erstellen, verwenden Sie die MessageBox-Klasse. Mit MessageBox können Sie den Text, den Titel, das Symbol und die Schaltflächen im Meldungsfeld konfigurieren, indem Sie Code wie den folgenden verwenden.

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

Zum Anzeigen eines Meldungsfelds rufen Sie die staticShow-Methode auf, wie im folgenden Code veranschaulicht.

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

Wenn Code, der ein Meldungsfeld anzeigt, die Entscheidung des Benutzers (welche Schaltfläche angeklickt wurde) erkennen und verarbeiten muss, kann der Code das Ergebnis des Meldungsfelds überprüfen, wie im folgenden Code gezeigt.

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

Weitere Informationen zur Verwendung von Nachrichtenfeldern finden Sie unter MessageBox, MessageBox-Beispiel und Dialogfeldbeispiel.

Zwar bietet MessageBox bereits eine einfache Dialogfeld-Benutzeroberfläche, der Vorteil der Verwendung von MessageBox liegt jedoch darin, dass es der einzige Fenstertyp ist, der von Anwendungen angezeigt werden kann, die in einer teilweise vertrauenswürdigen Sicherheitssandbox (siehe Sicherheit), ausgeführt werden, etwa XAML-Browseranwendungen (XBAPs).

In den meisten Dialogfeldern werden komplexere Daten angezeigt und gesammelt als im Ergebnis eines Meldungsfelds. Dazu zählen Text, Auswahlmöglichkeiten (Kontrollkästchen), sich gegenseitig ausschließende Auswahlmöglichkeiten (Optionsfelder) und Auswahlmöglichkeiten in einer Liste (Listenfelder, Kombinationsfelder, Dropdown-Listenfelder). Dafür stellt WPF (Windows Presentation Foundation) mehrere Standarddialogfelder zur Verfügung und ermöglicht es Ihnen, eigene Dialogfelder zu erstellen. Allerdings ist die Verwendung beider Typen auf Anwendungen begrenzt, die mit voller Vertrauenswürdigkeit ausgeführt werden.

Standarddialogfelder

Windows implementiert eine Reihe von wiederverwendbaren Dialogfeldern, die für alle Anwendungen gleich sind. Dazu zählen Dialogfelder zum Öffnen und Speichern von Dateien und zum Drucken. Da diese Dialogfelder durch das Betriebssystem implementiert werden, können sie von allen Anwendungen, die unter dem Betriebssystem ausgeführt werden, genutzt werden. Dies trägt zu einer konsistenten Benutzererfahrung bei: Wenn Benutzer mit der Verwendung eines durch das Betriebssystem bereitgestellten Dialogfelds in einer Anwendung vertraut sind, müssen Sie nicht lernen, wie sie dieses Dialogfeld in anderen Anwendungen verwenden. Da diese Dialogfelder allen Anwendungen zur Verfügung stehen und sie zu einer konsistenten Benutzererfahrung beitragen, werden sie als Standarddialogfelder bezeichnet.

WPF (Windows Presentation Foundation) kapselt die Standarddialogfelder zum Öffnen und Speichern von Dateien sowie zum Drucken und stellt sie als verwaltete Klassen für die Verwendung in eigenständigen Anwendungen zur Verfügung. Dieses Thema enthält eine kurze Übersicht über die einzelnen Dialogfelder.

Dialogfeld „Datei öffnen“

Das Dialogfeld „Datei öffnen“, das in der folgenden Abbildung gezeigt wird, wird von Funktionen zum Öffnen von Dateien verwendet, um den Namen einer zu öffnenden Datei abzurufen.

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

Das Standarddialogfeld „Datei öffnen“ ist als OpenFileDialog-Klasse implementiert und befindet sich im Microsoft.Win32-Namespace. Im folgenden Code wird gezeigt, wie ein solches Dialogfeld erstellt, konfiguriert und angezeigt und wie das Ergebnis verarbeitet wird.

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

Weitere Informationen zum Dialogfeld „Datei öffnen“ finden Sie unter Microsoft.Win32.OpenFileDialog.

Hinweis

Mit OpenFileDialog können Dateinamen von Anwendungen, die mit teilweiser Vertrauenswürdigkeit ausgeführt werden, sicher abgerufen werden (siehe Sicherheit).

Datei speichern (Dialogfeld)

Das Dialogfeld „Datei speichern“, das in der folgenden Abbildung gezeigt wird, wird von Funktionen zum Speichern von Dateien verwendet, um den Namen einer zu speichernden Datei abzurufen.

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

Das Standarddialogfeld „Datei speichern“ ist als SaveFileDialog-Klasse implementiert und befindet sich im Microsoft.Win32-Namespace. Im folgenden Code wird gezeigt, wie ein solches Dialogfeld erstellt, konfiguriert und angezeigt und wie das Ergebnis verarbeitet wird.

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

Weitere Informationen zum Dialogfeld „Datei speichern“ finden Sie unter Microsoft.Win32.SaveFileDialog.

Das Dialogfeld „Drucken“, das in der folgenden Abbildung gezeigt wird, wird von Funktionen zum Drucken verwendet, um den Drucker auszuwählen und zu konfigurieren, auf dem der Benutzer Daten ausgeben möchte.

Screenshot that shows a Print dialog box.

Das Standarddialogfeld „Drucken“ ist als PrintDialog-Klasse implementiert und befindet sich im System.Windows.Controls-Namespace. Im folgenden Code wird gezeigt, wie ein solches Dialogfeld erstellt, konfiguriert und angezeigt wird.

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

Weitere Informationen zum Dialogfeld "Datei drucken" finden Sie unter System.Windows.Controls.PrintDialog. Ausführliche Informationen über das Drucken in WPF finden Sie unter Übersicht über das Drucken.

Benutzerdefinierte Dialogfelder

Obwohl Standarddialogfelder hilfreich sind und nach Möglichkeit verwendet werden sollten, unterstützen sie nicht die Anforderungen von domänenspezifischen Dialogfeldern. In diesen Fällen müssen Sie eigene Dialogfelder erstellen. Wie später ersichtlich wird, ist ein Dialogfeld ein Fenster mit besonderen Verhaltensweisen. Window implementiert diese Verhaltensweisen, und Sie verwenden Window, um benutzerdefinierte modale und nicht modale Dialogfelder zu erstellen.

Erstellen eines modalen benutzerdefinierten Dialogfelds

In diesem Thema wird beschrieben, wie Window verwendet wird, um eine typische Implementierung eines modalen Dialogfelds zu erstellen. Das Dialogfeld Margins dient als Beispiel (siehe Dialogfeldbeispiel). Das Dialogfeld Margins wird in der folgenden Abbildung gezeigt.

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

Konfigurieren eines modalen Dialogfelds

Die Benutzeroberfläche für ein normales Dialogfeld enthält Folgendes:

  • Die verschiedenen Steuerelemente, die zum Erfassen der gewünschten Daten erforderlich sind.

  • Eine OK-Schaltfläche, auf die Benutzer klicken, um das Dialogfeld zu schließen, zur Funktion zurückzukehren und mit der Verarbeitung fortzufahren.

  • Eine Abbrechen-Schaltfläche, auf die Benutzer klicken, um das Dialogfeld zu schließen und zu verhindern, dass die Funktion die Verarbeitung fortsetzt.

  • Eine Schließen-Schaltfläche in der Titelleiste.

  • Symbol

  • Schaltflächen zum Minimieren, Maximieren und Wiederherstellen.

  • Ein Systemmenü zum Minimieren, Maximieren, Wiederherstellen und Schließen des Dialogfelds.

  • Eine Position mittig oberhalb des Fensters, das das Dialogfeld geöffnet hat.

  • Die Möglichkeit zum Ändern der Größe, damit das Dialogfeld nicht zu klein ist, und um dem Benutzer eine sinnvolle Standardgröße anzubieten. Dazu ist es erforderlich, dass Sie sowohl die Standard- als auch die Mindestabmessungen festlegen.

  • Die ESC-TASTE als Tastenkombination, die bewirkt, dass die Schaltfläche Abbrechen gedrückt wird. Dazu legen Sie die Eigenschaft IsCancel der Schaltfläche Abbrechen auf true fest.

  • Die EINGABETASTE als Tastenkombination, die das Drücken der Schaltfläche OK bewirkt. Dazu legen Sie die Eigenschaft IsDefault der Schaltfläche OK auf true fest.

Im folgenden Code wird diese Konfiguration veranschaulicht.

<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

Die Benutzererfahrung eines Dialogfelds setzt sich auch in der Menüleiste des Fensters fort, das das Dialogfeld öffnet. Wenn ein Menüelement eine Funktion ausführt, die eine Benutzerinteraktion über ein Dialogfeld benötigt, bevor die Funktion fortfahren kann, weist das Menüelement für die Funktion Auslassungszeichen im Header auf, wie nachfolgend gezeigt.

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

Wenn ein Menüelement eine Funktion ausführt, die ein Dialogfeld anzeigt, das ohne Benutzerinteraktion auskommt, z. B. das Dialogfeld „Info“, werden die Auslassungszeichen nicht benötigt.

Öffnen eines modalen Dialogfelds

Ein Dialogfeld wird üblicherweise als Ergebnis des Vorgangs angezeigt, bei dem ein Benutzer ein Menüelement auswählt, um eine domänenspezifische Funktion auszuführen, z. B. das Festlegen der Ränder eines Dokuments in einem Textverarbeitungsprogramm. Das Anzeigen eines Fensters als Dialogfeld ähnelt dem Anzeigen eines normalen Fensters, benötigt jedoch eine zusätzliche dialogfeldspezifische Konfiguration. Der vollständige Vorgang des Instanziierens, Konfigurierens und Öffnens eines Dialogfelds wird im folgenden Code gezeigt.

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

An dieser Stelle werden vom Code Standardinformationen (die aktuellen Ränder) an das Dialogfeld übergeben. Außerdem wird die Eigenschaft Window.Owner auf einen Verweis auf das Fenster festgelegt, in dem das Dialogfeld angezeigt wird. Im Allgemeinen sollten Sie immer den Besitzer eines Dialogfelds festlegen, um zustandsbezogenes Verhalten von Fenstern bereitzustellen, die für alle Dialogfelder gelten (weitere Informationen finden Sie unter Übersicht über WPF-Fenster).

Hinweis

Sie müssen einen Besitzer angeben, um die UI-Automatisierung (User Interface, Benutzeroberfläche) für Dialogfelder zu unterstützen (siehe dazu Übersicht über die Benutzeroberflächenautomatisierung).

Nachdem das Dialogfeld konfiguriert ist, wird es durch Aufrufen der Methode ShowDialog modal angezeigt.

Überprüfen der vom Benutzer bereitgestellten Daten

Wenn ein Dialogfeld geöffnet wird und der Benutzer die benötigten Daten zur Verfügung stellt, ist ein Dialogfeld aus folgenden Gründen dafür verantwortlich, dass die bereitgestellten Daten gültig sind:

  • Aus Gründen der Datensicherheit sollten alle Eingaben überprüft werden.

  • Aus domänenspezifischer Sicht verhindert die Datenvalidierung, dass fehlerhafte Daten vom Code verarbeitet werden, was zum Auslösen von Ausnahmen führen kann.

  • Aus Gründen der Benutzererfahrung kann ein Dialogfeld dazu beitragen, Benutzern zu helfen, indem ihnen gezeigt wird, welche der von ihnen eingegebenen Daten ungültig sind.

  • Unter Leistungsaspekten betrachtet, kann die Datenvalidierung in einer Anwendung mit mehreren Ebenen die Anzahl von Roundtrips zwischen der Client- und der Anwendungsebene vermindern, insbesondere, wenn die Anwendung aus Webdiensten oder serverbasierten Datenbanken besteht.

Zum Überprüfen eines gebundenen Steuerelements in WPF müssen Sie eine Validierungsregel angeben und sie der Bindung zuordnen. Eine Validierungsregel ist eine benutzerdefinierte Klasse, die von ValidationRule abgeleitet ist. Im folgenden Beispiel wird die Validierungsregel MarginValidationRule gezeigt, die überprüft, ob ein gebundener Wert ein Double ist und in einem angegebenen Bereich liegt.

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

In diesem Code wird die Validierungsregel durch Außerkraftsetzen der Methode Validate implementiert, die die Daten überprüft und ein entsprechendes ValidationResult zurückgibt.

Um die Validierungsregel dem gebundenen Steuerelement zuzuordnen, wird das folgende Markup verwendet.

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

Nachdem die Validierungsregel zugeordnet ist, wird sie von WPF automatisch angewendet, wenn Daten in das gebundene Steuerelement eingegeben werden. Wenn ein Steuerelement ungültige Daten enthält, wird das ungültige Steuerelement von WPF mit einem roten Rahmen angezeigt, wie in der folgenden Abbildung gezeigt.

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

WPF beschränkt Benutzer nicht so lange auf das ungültige Steuerelement, bis sie gültige Daten eingegeben haben. Das wird als gutes Verhalten für ein Dialogfeld verstanden: Benutzer sollten in einem Dialogfeld frei durch die Steuerelemente navigieren können, unabhängig davon, ob die Daten gültig sind. Dies bedeutet allerdings, dass ein Benutzer ungültige Daten eingeben und auf die Schaltfläche OK klicken kann. Aus diesem Grund muss Ihr Code auch für die Überprüfung aller Steuerelemente in einem Dialogfeld sorgen, wenn auf die Schaltfläche OK geklickt wird. Dies geschieht durch Behandlung des Click-Ereignisses.

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

Von diesem Code werden alle Abhängigkeitsobjekte in einem Fenster aufgelistet. Befinden sich ungültige Objekte darunter, (wie sie von GetHasError zurückgegeben werden), erhält das ungültige Steuerelement den Fokus, die IsValid-Methode gibt false zurück, und das Fenster wird als ungültig angesehen.

Sobald ein Dialogfeld gültig ist, kann es sicher geschlossen und zurückgegeben werden. Als Teil des Rückgabevorgangs muss es ein Ergebnis an die aufrufende Funktion zurückgeben.

Festlegen des Ergebnisses eines modalen Dialogfelds

Das Öffnen eines Dialogfelds mit ShowDialog entspricht grundsätzlich dem Aufrufen einer Methode: Der Code, der das Dialogfeld mithilfe von ShowDialog geöffnet hat, wartet, bis ShowDialog zurückkehrt. Wenn ShowDialog zurückkehrt, muss der Code, der es aufgerufen hat, entscheiden, ob die Verarbeitung fortgesetzt oder abgebrochen wird, je nachdem, ob der Benutzer auf die Schaltfläche OK oder auf Abbrechen geklickt hat. Zum Erleichtern dieser Entscheidung muss das Dialogfeld die Auswahl des Benutzers als Boolean-Wert zurückgeben, der von der Methode ShowDialog zurückgegeben wird.

Wenn auf die Schaltfläche OK geklickt wird, sollte ShowDialogtrue zurückgeben. Dies wird erreicht, indem die DialogResult-Eigenschaft des Dialogfelds festgelegt wird, wenn auf die Schaltfläche OK geklickt wird.

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

Beachten Sie, dass das Festlegen der DialogResult-Eigenschaft zugleich das automatische Schließen des Fensters bewirkt, was den expliziten Aufruf von Close überflüssig macht.

Wenn auf die Schaltfläche Abbrechen geklickt wird, sollte ShowDialogfalse zurückgeben, wofür ebenfalls das Festlegen der DialogResult-Eigenschaft erforderlich ist.

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

Wenn die Eigenschaft IsCancel einer Schaltfläche auf true festgelegt ist und der Benutzer entweder auf die Schaltfläche Abbrechen klickt oder die ESC-Taste drückt, wird DialogResult automatisch auf false festgelegt. Das folgende Markup hat denselben Effekt wie der vorhergehende Code, ohne dass das Click-Ereignis behandelt werden muss.

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

Ein Dialogfeld gibt automatisch false zurück, wenn ein Benutzer in der Titelleiste auf die Schaltfläche Schließen klickt oder im Systemmenü das Menüelement Schließen auswählt.

Verarbeiten von Daten, die von einem modalen Dialogfeld zurückgegeben werden

Wenn DialogResult von einem Dialogfeld festgelegt wird, kann die Funktion, die es geöffnet hat, das Ergebnis des Dialogfelds abrufen, indem es die Eigenschaft DialogResult in der Rückgabe von ShowDialog untersucht.

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

Wenn das Dialogergebnis true ist, wird dies von der Funktion als Hinweis verwendet, die vom Benutzer bereitgestellten Daten abzurufen und zu verarbeiten.

Hinweis

Nach der Rückkehr von ShowDialog kann ein Dialogfeld nicht mehr geöffnet werden. Stattdessen müssen Sie eine neue Instanz erstellen.

Wenn das Dialogergebnis false ist, sollte die Funktion die Verarbeitung entsprechend beenden.

Erstellen eines nicht modalen benutzerdefinierten Dialogfelds

Ein nicht modales Dialogfeld, z. B. das in der folgenden Abbildung dargestellte Dialogfeld „Suchen“, besitzt dasselbe grundlegende Aussehen wie das modale Dialogfeld.

Screenshot that shows a Find dialog box.

Allerdings ist das Verhalten etwas anders, wie in den folgenden Abschnitten beschrieben wird.

Öffnen eines nicht modalen Dialogfelds

Ein nicht modales Dialogfeld wird durch Aufrufen der Methode Show geöffnet.

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

Im Gegensatz zu ShowDialog kehrt Show sofort zurück. Dementsprechend kann das aufrufende Fenster nicht erkennen, wann das nicht modale Dialogfeld geschlossen wird, und weiß deshalb auch nicht, wann es ein Dialogfeldergebnis überprüfen oder Daten vom Dialogfeld zur weiteren Verarbeitung abrufen soll. Stattdessen muss vom Dialogfeld eine andere Möglichkeit erstellt werden, um Daten an das aufrufende Fenster zur Verarbeitung zurückzugeben.

Verarbeiten von Daten, die von einem nicht modalen Dialogfeld zurückgegeben werden

In diesem Beispiel kann FindDialogBox ein oder mehrere Suchergebnisse an das Hauptfenster zurückgeben, je nach Suchtext ohne besondere Häufigkeit. Wie ein modales Dialogfeld kann auch ein nicht modales Dialogfeld Ergebnisse mithilfe von Eigenschaften zurückgeben. Das Fenster, das Besitzer des Dialogfelds ist, muss jedoch wissen, wann es diese Eigenschaften überprüfen soll. Diese Funktionalität kann z. B. dadurch aktiviert werden, dass das Dialogfeld ein Ereignis implementiert, das jedes Mal ausgelöst wird, wenn Text gefunden wird. FindDialogBox implementiert zu diesem Zweck TextFoundEvent, wobei zuerst ein Delegat erforderlich ist.

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

Mithilfe des TextFoundEventHandler-Delegaten implementiert FindDialogBox das 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

Infolgedessen kann Find das Ereignis auslösen, wenn ein Suchergebnis gefunden wird.

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

Das Besitzerfenster muss anschließend bei diesem Ereignis registriert werden und es behandeln.

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

Schließen eines nicht modalen Dialogfelds

Weil DialogResult nicht festgelegt werden muss, kann ein nicht modales Dialogfeld mithilfe von systemeigenen Mechanismen geschlossen werden. Dazu zählen:

  • Klicken auf die Schaltfläche Schließen in der Titelleiste.

  • Drücken von ALT+F4.

  • Auswählen von Schließen im Systemmenü.

Der Code kann alternativ Close aufrufen, wenn auf die Schaltfläche Schließen geklickt wird.

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

Siehe auch