Übersicht über Dialogfelder
Aktualisiert: November 2007
Eigenständige Anwendungen verfügen üblicherweise über ein Hauptfenster, in dem die wichtigen Daten, mit denen die Anwendung arbeitet, angezeigt werden, und das die Funktionen verfügbar macht, um diese Daten mithilfe von Benutzeroberfläche (user interface, UI)-Mechanismen wie Menüleisten, Symbolleisten und Statusleisten zu verarbeiten. Eine wichtige Anwendung kann auch zusätzliche Fenster anzeigen, um folgende Aufgaben auszuführen:
Anzeigen von besonderen Informationen für Benutzer.
Erfassen von Informationen von Benutzern.
Anzeigen und Erfassen von Informationen.
Diese Typen von Fenstern werden als Dialogfelder bezeichnet. Es gibt zwei Typen: modale und nicht modale.
Ein modales Dialogfeld wird durch eine Funktion angezeigt, wenn die Funktion zum Fortfahren zusätzliche Daten von einem Benutzer benötigt. Da die Funktion zum Sammeln der Daten vom modalen Dialogfeld abhängig ist, verhindert das modale Dialogfeld, so lange es geöffnet ist, auch, dass ein Benutzer andere Fenster in der Anwendung aktiviert. 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 Windows Presentation Foundation (WPF) können Sie mehrere Typen von Dialogfeldern erstellen. Dazu zählen Meldungsfelder, Standarddialogfelder und benutzerdefinierte Dialogfelder. In diesem Thema wird jeder dieser Typen erläutert, und das Beispiel für ein Dialogfeld enthält entsprechende Beispiele.
Dieses Thema enthält folgende Abschnitte.
- Meldungsfelder
- Häufig verwendete Dialogfelder
- Benutzerdefinierte Dialogfelder
- Verwandte Abschnitte
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.
Ein Meldungsfeld wird mithilfe der MessageBox-Klasse erstellt. Mit MessageBox können Sie den Text, den Titel, das Symbol und die Schaltflächen im Meldungsfeld konfigurieren, indem Sie folgenden Code verwenden.
Um ein Meldungsfeld anzuzeigen, rufen Sie die static Show-Methode auf, wie im folgenden Code veranschaulicht.
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.
Weitere Informationen über die Verwendung von Meldungsfeldern finden Sie unter MessageBox, Beispiel zu MessageBox und unter Beispiel für ein Dialogfeld.
Obwohl MessageBox bereits ein einfaches Beispiel für die Benutzererfahrung mit Dialogfeldern bietet, liegt der Vorteil der Verwendung von MessageBox darin, dass es der einzige Fenstertyp ist, der von Anwendungen angezeigt werden kann, die in einer teilweise vertrauenswürdigen Sicherheitssandbox (siehe Windows Presentation Foundation-Sicherheit), z. B. XAML-Browseranwendungen (XBAPs), ausgeführt werden.
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 Windows Presentation Foundation (WPF) mehrere Standarddialogfelder zur Verfügung und ermöglicht es Ihnen, eigene Dialogfelder zu erstellen, obwohl die Verwendung beider Typen auf Anwendungen begrenzt ist, die mit voller Vertrauenswürdigkeit ausgeführt werden.
Häufig verwendete Dialogfelder
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.
Windows Presentation Foundation (WPF) 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.
Der Standarddialogfeld Datei öffnen wird 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.
Weitere Informationen über das Dialogfeld Datei öffnen finden Sie unter Microsoft.Win32.OpenFileDialog.
Tipp
Mit OpenFileDialog können Dateinamen von Anwendungen, die mit teilweiser Vertrauenswürdigkeit ausgeführt werden, sicher abgerufen werden (siehe Windows Presentation Foundation-Sicherheit). Ein Beispiel dazu finden Sie unter Beispiel für den sicheren Dateiupload von einem XBAP.
Dialogfeld "Datei speichern"
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.
Der Standarddialogfeld Datei speichern wird 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.
Weitere Informationen über das Dialogfeld Datei speichern finden Sie unter Microsoft.Win32.SaveFileDialog.
Dialogfeld "Drucken"
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.
Der Standarddialogfeld Drucken wird 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.
Weitere Informationen über das Dialogfeld 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 speziellem Verhalten. Window implementiert diese Verhalten, und dementsprechend erstellen Sie mit Window benutzerdefinierte modale und nicht modale Dialogfelder.
Erstellen eines modalen benutzerdefinierten Dialogfelds
In diesem Thema wird erläutert, wie mithilfe von Window ein typisches modales Dialogfeld implementiert wird. Das Dialogfeld Margins dient dabei als Beispiel (siehe Beispiel für ein Dialogfeld). Das Dialogfeld Margins wird in der folgenden Abbildung angezeigt.
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.
Ein Symbol.
Schaltflächen zum Minimieren, Maximieren und Wiederherstellen.
Ein Systemmenü zum Minimieren, Maximieren, Wiederherstellen und Schließen des Dialogfelds.
Eine freie Stelle über und in der Mitte des Fensters, das das Dialogfeld geöffnet hat.
Die Größe von Dialogfeldern sollte sich nach Möglichkeit ändern lassen. Um zu verhindern, dass das Dialogfeld zu klein ist, und um für den Benutzer eine sinnvolle Standardgröße bereitzustellen, müssen Sie jeweils die Standard- und Mindestgröße festlegen.
Das Drücken der ESC-TASTE sollte als Tastenkombination konfiguriert werden, die bewirkt, dass die Schaltfläche Abbrechen gedrückt wird. Dies wird erreicht, indem die IsCancel-Eigenschaft der Schaltfläche Abbrechen auf true festgelegt wird.
Das Drücken der EINGABETASTE sollte als Tastenkombination konfiguriert werden, die bewirkt, dass die Schaltfläche OK gedrückt wird. Dies wird erreicht, indem die IsDefault-Eigenschaft der Schaltfläche OK auf true festgelegt wird.
Im folgenden Code wird diese Konfiguration veranschaulicht.
<Window
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://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>
Imports System.Windows ' Window, RoutedEventArgs, IInputElement, DependencyObject
Imports System.Windows.Controls ' Validation
Imports System.Windows.Input ' Keyboard
Namespace SDKSample
Public Class MarginsDialogBox
Inherits Window
Public Sub New()
Me.InitializeComponent()
End Sub
...
End Class
End Namespace
using System.Windows; // Window, RoutedEventArgs, IInputElement, DependencyObject
using System.Windows.Controls; // Validation
using System.Windows.Input; // Keyboard
namespace SDKSample
{
public partial class MarginsDialogBox : Window
{
public MarginsDialogBox()
{
InitializeComponent();
}
...
}
}
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.
Imports System ' EventArgs
Imports System.ComponentModel ' CancelEventArgs
Imports System.Windows ' Window, MessageBoxXxx, RoutedEventArgs
Imports System.Windows.Controls ' TextChangedEventArgs
Imports Microsoft.Win32 ' OpenFileDialog
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
using System; // EventArgs
using System.ComponentModel; // CancelEventArgs
using System.Windows; // Window, MessageBoxXxx, RoutedEventArgs
using System.Windows.Controls; // TextChangedEventArgs
using Microsoft.Win32; // OpenFileDialog
namespace SDKSample
{
public partial class MainWindow : Window
{
...
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();
...
}
...
}
}
An dieser Stelle werden vom Code Standardinformationen (die aktuellen Ränder) an das Dialogfeld übergeben. Im Beispiel wird auch die Window.Owner-Eigenschaft mit einem Verweis auf das Fenster, das das Dialogfeld anzeigt, festgelegt. 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).
Tipp
Sie müssen einen Besitzer bereitstellen, um die Benutzeroberfläche (user interface, UI)-Automatisierung für Dialogfelder zu unterstützen (siehe Übersicht über die Benutzeroberflächenautomatisierung).
Nachdem das Dialogfeld konfiguriert ist, wird es durch Aufrufen der ShowDialog-Methode 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.
Um ein gebundenes Steuerelement in WPF zu überprüfen, muss eine Validierungsregel definiert und der Bindung zugeordnet werden. Eine Validierungsregel ist eine benutzerdefinierte Klasse, die von ValidationRule abgeleitet wird. Im folgenden Beispiel wird die Validierungsregel MarginValidationRule gezeigt, die überprüft, ob ein gebundener Wert ein Double ist und in einem bestimmten Bereich liegt.
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
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);
}
}
}
In diesem Code wird die Validierungslogik einer Validierungsregel durch Überschreiben der Validate-Methode 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="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://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>
...
<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>
...
</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.
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 müssen alle Steuerelemente in einem Dialogfeld vom Code auch überprüft werden, wenn auf die Schaltfläche OK geklickt wird. Dies geschieht durch Behandlung des Click-Ereignisses.
Imports System.Windows ' Window, RoutedEventArgs, IInputElement, DependencyObject
Imports System.Windows.Controls ' Validation
Imports System.Windows.Input ' Keyboard
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
using System.Windows; // Window, RoutedEventArgs, IInputElement, DependencyObject
using System.Windows.Controls; // Validation
using System.Windows.Input; // Keyboard
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;
}
}
}
Alle Abhängigkeitsobjekte in einem Fenster werden von diesem Code 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 modalen Dialogergebnisses
Das Öffnen eines Dialogfelds mithilfe von ShowDialog entspricht im Wesentlichen dem Aufruf einer Methode: Der Code, der das Dialogfeld mithilfe von ShowDialog geöffnet hat, wartet, bis ShowDialog zurückgegeben wird. Wenn ShowDialog zurückgegeben wird, muss der Code, der die Methode 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. Um diese Entscheidung zu erleichtern, muss das Dialogfeld die Auswahl des Benutzers als Boolean Wert zurückgeben, der von der ShowDialog-Methode zurückgegeben wird.
Wenn auf die Schaltfläche OK geklickt wurde, sollte ShowDialogtrue zurückgeben. Dies wird erreicht, indem die DialogResult-Eigenschaft des Dialogfelds festgelegt wird, wenn auf die Schaltfläche OK geklickt wird.
Beachten Sie, dass das Festlegen der DialogResult-Eigenschaft auch bewirkt, dass das Fenster automatisch geschlossen wird, wodurch Close nicht explizit aufgerufen werden muss.
Wenn auf die Schaltfläche Abbrechen geklickt wird, sollte ShowDialogfalse zurückgeben, wodurch es auch erforderlich wird, die DialogResult-Eigenschaft festzulegen.
Imports System.Windows ' Window, RoutedEventArgs, IInputElement, DependencyObject
Imports System.Windows.Controls ' Validation
Imports System.Windows.Input ' Keyboard
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
using System.Windows; // Window, RoutedEventArgs, IInputElement, DependencyObject
using System.Windows.Controls; // Validation
using System.Windows.Input; // Keyboard
namespace SDKSample
{
public partial class MarginsDialogBox : Window
{
...
void cancelButton_Click(object sender, RoutedEventArgs e)
{
// Dialog box canceled
this.DialogResult = false;
}
...
}
}
Wenn die IsCancel-Eigenschaft einer Schaltfläche auf true festgelegt wird und der Benutzer 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 true 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 Dialogfeldergebnis abrufen, indem sie die DialogResult-Eigenschaft überprüft, wenn ShowDialog zurückgegeben wird.
Imports System ' EventArgs
Imports System.ComponentModel ' CancelEventArgs
Imports System.Windows ' Window, MessageBoxXxx, RoutedEventArgs
Imports System.Windows.Controls ' TextChangedEventArgs
Imports Microsoft.Win32 ' OpenFileDialog
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
using System; // EventArgs
using System.ComponentModel; // CancelEventArgs
using System.Windows; // Window, MessageBoxXxx, RoutedEventArgs
using System.Windows.Controls; // TextChangedEventArgs
using Microsoft.Win32; // OpenFileDialog
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;
}
}
...
}
}
Wenn das Dialogergebnis true ist, wird dies von der Funktion als Hinweis verwendet, um die vom Benutzer bereitgestellten Daten abzurufen und zu verarbeiten.
Tipp
Nachdem ShowDialog zurückgegeben wurde, kann ein Dialogfeld nicht erneut 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.
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 Show-Methode geöffnet.
<!--Main Window-->
Imports System ' EventArgs
Imports System.ComponentModel ' CancelEventArgs
Imports System.Windows ' Window, MessageBoxXxx, RoutedEventArgs
Imports System.Windows.Controls ' TextChangedEventArgs
Imports Microsoft.Win32 ' OpenFileDialog
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
using System; // EventArgs
using System.ComponentModel; // CancelEventArgs
using System.Windows; // Window, MessageBoxXxx, RoutedEventArgs
using System.Windows.Controls; // TextChangedEventArgs
using Microsoft.Win32; // OpenFileDialog
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();
}
...
}
}
Im Gegensatz zu ShowDialog wird Show sofort zurückgegeben. 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. Eine Möglichkeit, dies zu ermöglichen, besteht darin, für das Dialogfeld ein Ereignis zu implementieren, das immer dann ausgelöst wird, wenn Text gefunden wird. FindDialogBox implementiert zu diesem Zweck TextFoundEvent, wozu zunächst ein Delegat benötigt wird.
Namespace SDKSample
Public Delegate Sub TextFoundEventHandler(ByVal sender As Object, ByVal e As EventArgs)
End Namespace
using System;
namespace SDKSample
{
public delegate void TextFoundEventHandler(object sender, EventArgs e);
}
Mithilfe des TextFoundEventHandler-Delegaten implementiert FindDialogBox das TextFoundEvent.
Imports System ' EventArgs
Imports System.Windows ' Window, MessageBoxXxx, RoutedEventArgs
Imports System.Windows.Controls ' TextBox, TextChangedEventArgs
Imports System.Text.RegularExpressions ' Regex
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
using System; // EventArgs
using System.Windows; // Window, MessageBoxXxx, RoutedEventArgs
using System.Windows.Controls; // TextBox, TextChangedEventArgs
using System.Text.RegularExpressions; // Regex
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);
}
...
}
}
Infolgedessen kann Find das Ereignis auslösen, wenn ein Suchergebnis gefunden wird.
Imports System ' EventArgs
Imports System.Windows ' Window, MessageBoxXxx, RoutedEventArgs
Imports System.Windows.Controls ' TextBox, TextChangedEventArgs
Imports System.Text.RegularExpressions ' Regex
Namespace SDKSample
Public Class FindDialogBox
Inherits Window
...
Private Sub findNextButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
...
Me.Index = match.Index
Me.Length = match.Length
RaiseEvent TextFound(Me, EventArgs.Empty)
...
End Sub
...
End Class
End Namespace
using System; // EventArgs
using System.Windows; // Window, MessageBoxXxx, RoutedEventArgs
using System.Windows.Controls; // TextBox, TextChangedEventArgs
using System.Text.RegularExpressions; // Regex
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();
...
}
...
}
}
Das Besitzerfenster muss anschließend bei diesem Ereignis registriert werden und es behandeln.
Imports System ' EventArgs
Imports System.ComponentModel ' CancelEventArgs
Imports System.Windows ' Window, MessageBoxXxx, RoutedEventArgs
Imports System.Windows.Controls ' TextChangedEventArgs
Imports Microsoft.Win32 ' OpenFileDialog
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
using System; // EventArgs
using System.ComponentModel; // CancelEventArgs
using System.Windows; // Window, MessageBoxXxx, RoutedEventArgs
using System.Windows.Controls; // TextChangedEventArgs
using Microsoft.Win32; // OpenFileDialog
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();
}
}
}
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.
Imports System ' EventArgs
Imports System.Windows ' Window, MessageBoxXxx, RoutedEventArgs
Imports System.Windows.Controls ' TextBox, TextChangedEventArgs
Imports System.Text.RegularExpressions ' Regex
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
using System; // EventArgs
using System.Windows; // Window, MessageBoxXxx, RoutedEventArgs
using System.Windows.Controls; // TextBox, TextChangedEventArgs
using System.Text.RegularExpressions; // Regex
namespace SDKSample
{
public partial class FindDialogBox : Window
{
...
void closeButton_Click(object sender, RoutedEventArgs e)
{
// Close dialog box
this.Close();
}
}
}
Siehe auch
Aufgaben
Beispiel für einen Assistenten
Beispiel zum benutzerdefinierten ColorPicker-Steuerelement
Demo für das Dialogfeld "Schriftart"