Dialog boxes overview
Standalone applications typically have a main window that both displays the main data over which the application operates and exposes the functionality to process that data through user interface (UI) mechanisms like menu bars, tool bars, and status bars. A non-trivial application may also display additional windows to do the following:
Display specific information to users.
Gather information from users.
Both display and gather information.
These types of windows are known as dialog boxes, and there are two types: modal and modeless.
A modal dialog box is displayed by a function when the function needs additional data from a user to continue. Because the function depends on the modal dialog box to gather data, the modal dialog box also prevents a user from activating other windows in the application while it remains open. In most cases, a modal dialog box allows a user to signal when they have finished with the modal dialog box by pressing either an OK or Cancel button. Pressing the OK button indicates that a user has entered data and wants the function to continue processing with that data. Pressing the Cancel button indicates that a user wants to stop the function from executing altogether. The most common examples of modal dialog boxes are shown to open, save, and print data.
A modeless dialog box, on the other hand, does not prevent a user from activating other windows while it is open. For example, if a user wants to find occurrences of a particular word in a document, a main window will often open a dialog box to ask a user what word they are looking for. Since finding a word doesn't prevent a user from editing the document, however, the dialog box doesn't need to be modal. A modeless dialog box at least provides a Close button to close the dialog box, and may provide additional buttons to execute specific functions, such as a Find Next button to find the next word that matches the find criteria of a word search.
Windows Presentation Foundation (WPF) allows you to create several types of dialog boxes, including message boxes, common dialog boxes, and custom dialog boxes. This topic discusses each, and the Dialog Box Sample provides matching examples.
Message boxes
A message box is a dialog box that can be used to display textual information and to allow users to make decisions with buttons. The following figure shows a message box that displays textual information, asks a question, and provides the user with three buttons to answer the question.
To create a message box, you use the MessageBox class. MessageBox lets you configure the message box text, title, icon, and buttons, using code like the following.
// 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
To show a message box, you call the static
Show method, as demonstrated in the following code.
// Display message box
MessageBox.Show(messageBoxText, caption, button, icon);
' Display message box
MessageBox.Show(messageBoxText, caption, button, icon)
When code that shows a message box needs to detect and process the user's decision (which button was pressed), the code can inspect the message box result, as shown in the following code.
// 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
For more information on using message boxes, see MessageBox, MessageBox Sample, and Dialog Box Sample.
Although MessageBox may offer a simple dialog box user experience, the advantage of using MessageBox is that is the only type of window that can be shown by applications that run within a partial trust security sandbox (see Security), such as XAML browser applications (XBAPs).
Most dialog boxes display and gather more complex data than the result of a message box, including text, selection (check boxes), mutually exclusive selection (radio buttons), and list selection (list boxes, combo boxes, drop-down list boxes). For these, Windows Presentation Foundation (WPF) provides several common dialog boxes and allows you to create your own dialog boxes, although the use of either is limited to applications running with full trust.
Common dialog boxes
Windows implements a variety of reusable dialog boxes that are common to all applications, including dialog boxes for opening files, saving files, and printing. Since these dialog boxes are implemented by the operating system, they can be shared among all the applications that run on the operating system, which helps user experience consistency; when users are familiar with the use of an operating system-provided dialog box in one application, they don't need to learn how to use that dialog box in other applications. Because these dialog boxes are available to all applications and because they help provide a consistent user experience, they are known as common dialog boxes.
Windows Presentation Foundation (WPF) encapsulates the open file, save file, and print common dialog boxes and exposes them as managed classes for you to use in standalone applications. This topic provides a brief overview of each.
Open File dialog
The open file dialog box, shown in the following figure, is used by file opening functionality to retrieve the name of a file to open.
The common open file dialog box is implemented as the OpenFileDialog class and is located in the Microsoft.Win32 namespace. The following code shows how to create, configure, and show one, and how to process the result.
// 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
For more information on the open file dialog box, see Microsoft.Win32.OpenFileDialog.
Note
OpenFileDialog can be used to safely retrieve file names by applications running with partial trust (see Security).
Save File dialog box
The save file dialog box, shown in the following figure, is used by file saving functionality to retrieve the name of a file to save.
The common save file dialog box is implemented as the SaveFileDialog class, and is located in the Microsoft.Win32 namespace. The following code shows how to create, configure, and show one, and how to process the result.
// 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
For more information on the save file dialog box, see Microsoft.Win32.SaveFileDialog.
Print dialog box
The print dialog box, shown in the following figure, is used by printing functionality to choose and configure the printer that a user would like to print data to.
The common print dialog box is implemented as the PrintDialog class, and is located in the System.Windows.Controls namespace. The following code shows how to create, configure, and show one.
// 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
For more information on the print dialog box, see System.Windows.Controls.PrintDialog. For detailed discussion of printing in WPF, see Printing Overview.
Custom dialog boxes
While common dialog boxes are useful, and should be used when possible, they do not support the requirements of domain-specific dialog boxes. In these cases, you need to create your own dialog boxes. As we'll see, a dialog box is a window with special behaviors. Window implements those behaviors and, consequently, you use Window to create custom modal and modeless dialog boxes.
Creating a modal custom dialog box
This topic shows how to use Window to create a typical modal dialog box implementation, using the Margins
dialog box as an example (see Dialog Box Sample). The Margins
dialog box is shown in the following figure.
Configuring a modal dialog box
The user interface for a typical dialog box includes the following:
The various controls that are required to gather the desired data.
An OK button that users click to close the dialog box, return to the function, and continue processing.
A Cancel button that users click to close the dialog box and stop the function from further processing.
A Close button in the title bar.
An icon.
Minimize, Maximize, and Restore buttons.
A System menu to minimize, maximize, restore, and close the dialog box.
A position above and in the center of the window that opened the dialog box.
The ability to be resized where possible to prevent the dialog box from being too small, and to provide the user with a useful default size. This requires that you set both the default and a minimum dimensions.
The ESC key as a keyboard shortcut that causes the Cancel button to be pressed. You do this by setting the IsCancel property of the Cancel button to
true
.The ENTER (or RETURN) key as a keyboard shortcut that causes the OK button to be pressed. You do this by setting the IsDefault property of the OK button
true
.
The following code demonstrates this configuration.
<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
The user experience for a dialog box also extends into the menu bar of the window that opens the dialog box. When a menu item runs a function that requires user interaction through a dialog box before the function can continue, the menu item for the function will have an ellipsis in its header, as shown here.
<!--Main Window-->
<MenuItem Name="formatMarginsMenuItem" Header="_Margins..." Click="formatMarginsMenuItem_Click" />
When a menu item runs a function that displays a dialog box which does not require user interaction, such as an About dialog box, an ellipsis is not required.
Opening a modal dialog box
A dialog box is typically shown as a result of a user selecting a menu item to perform a domain-specific function, such as setting the margins of a document in a word processor. Showing a window as a dialog box is similar to showing a normal window, although it requires additional dialog box-specific configuration. The entire process of instantiating, configuring, and opening a dialog box is shown in the following code.
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
Here, the code passes default information (the current margins) to the dialog box. It also sets the Window.Owner property with a reference to the window that is showing the dialog box. In general, you should always set the owner for a dialog box to provide window state-related behaviors that are common to all dialog boxes (see WPF Windows Overview for more information).
Note
You must provide an owner to support user interface (UI) automation for dialog boxes (see UI Automation Overview).
After the dialog box is configured, it is shown modally by calling the ShowDialog method.
Validating user-provided data
When a dialog box is opened and the user provides the required data, a dialog box is responsible for ensuring that the provided data is valid for the following reasons:
From a security perspective, all input should be validated.
From a domain-specific perspective, data validation prevents erroneous data from being processed by the code, which could potentially throw exceptions.
From a user-experience perspective, a dialog box can help users by showing them which data they have entered is invalid.
From a performance perspective, data validation in a multi-tier application can reduce the number of round trips between the client and the application tiers, particularly when the application is composed of Web services or server-based databases.
To validate a bound control in WPF, you need to define a validation rule and associate it with the binding. A validation rule is a custom class that derives from ValidationRule. The following example shows a validation rule, MarginValidationRule
, which checks that a bound value is a Double and is within a specified range.
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 this code, the validation logic of a validation rule is implemented by overriding the Validate method, which validates the data and returns an appropriate ValidationResult.
To associate the validation rule with the bound control, you use the following markup.
<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>
Once the validation rule is associated, WPF will automatically apply it when data is entered into the bound control. When a control contains invalid data, WPF will display a red border around the invalid control, as shown in the following figure.
WPF does not restrict a user to the invalid control until they have entered valid data. This is good behavior for a dialog box; a user should be able to freely navigate the controls in a dialog box whether or not data is valid. However, this means a user can enter invalid data and press the OK button. For this reason, your code also needs to validate all controls in a dialog box when the OK button is pressed by handling the Click event.
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
This code enumerates all dependency objects on a window and, if any are invalid (as returned by GetHasError, the invalid control gets the focus, the IsValid
method returns false
, and the window is considered invalid.
Once a dialog box is valid, it can safely close and return. As part of the return process, it needs to return a result to the calling function.
Setting the modal dialog result
Opening a dialog box using ShowDialog is fundamentally like calling a method: the code that opened the dialog box using ShowDialog waits until ShowDialog returns. When ShowDialog returns, the code that called it needs to decide whether to continue processing or stop processing, based on whether the user pressed the OK button or the Cancel button. To facilitate this decision, the dialog box needs to return the user's choice as a Boolean value that is returned from the ShowDialog method.
When the OK button is clicked, ShowDialog should return true
. This is achieved by setting the DialogResult property of the dialog box when the OK button is clicked.
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
Note that setting the DialogResult property also causes the window to close automatically, which alleviates the need to explicitly call Close.
When the Cancel button is clicked, ShowDialog should return false
, which also requires setting the DialogResult property.
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
When a button's IsCancel property is set to true
and the user presses either the Cancel button or the ESC key, DialogResult is automatically set to false
. The following markup has the same effect as the preceding code, without the need to handle the Click event.
<Button Name="cancelButton" IsCancel="True">Cancel</Button>
A dialog box automatically returns false
when a user presses the Close button in the title bar or chooses the Close menu item from the System menu.
Processing data returned from a modal dialog box
When DialogResult is set by a dialog box, the function that opened it can get the dialog box result by inspecting the DialogResult property when ShowDialog returns.
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
If the dialog result is true
, the function uses that as a cue to retrieve and process the data provided by the user.
Note
After ShowDialog has returned, a dialog box cannot be reopened. Instead, you need to create a new instance.
If the dialog result is false
, the function should end processing appropriately.
Creating a modeless custom dialog box
A modeless dialog box, such as the Find Dialog Box shown in the following figure, has the same fundamental appearance as the modal dialog box.
However, the behavior is slightly different, as described in the following sections.
Opening a modeless dialog box
A modeless dialog box is opened by calling the Show method.
<!--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
Unlike ShowDialog, Show returns immediately. Consequently, the calling window cannot tell when the modeless dialog box is closed and, therefore, does not know when to check for a dialog box result or get data from the dialog box for further processing. Instead, the dialog box needs to create an alternative way to return data to the calling window for processing.
Processing data returned from a modeless dialog box
In this example, the FindDialogBox
may return one or more find results to the main window, depending on the text being searched for without any specific frequency. As with a modal dialog box, a modeless dialog box can return results using properties. However, the window that owns the dialog box needs to know when to check those properties. One way to enable this is for the dialog box to implement an event that is raised whenever text is found. FindDialogBox
implements the TextFoundEvent
for this purpose, which first requires a delegate.
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
Using the TextFoundEventHandler
delegate, FindDialogBox
implements the 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
Consequently, Find
can raise the event when a search result is found.
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
The owner window then needs to register with and handle this event.
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
Closing a modeless dialog box
Because DialogResult does not need to be set, a modeless dialog can be closed using system provide mechanisms, including the following:
Clicking the Close button in the title bar.
Pressing ALT+F4.
Choosing Close from the System menu.
Alternatively, your code can call Close when the Close button is clicked.
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
See also
.NET Desktop feedback