對話方塊概觀Dialog Boxes Overview

獨立應用程式通常具有主視窗,其中顯示的主要資料的應用程式運作,並公開的功能來處理該資料透過使用者介面 (UI)user interface (UI)功能表列、 工具列和狀態列等機制。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 使用者介面 (UI)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強制回應函式需要額外的資料,從繼續使用者時,將會顯示函式的對話方塊。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非強制回應 對話方塊中,相反地,不會防止使用者啟動其他視窗開啟時。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. 非強制回應對話方塊至少會提供關閉按鈕以關閉對話方塊,並可能會提供其他按鈕來執行特定函式,例如尋找下一個按鈕來尋找下一步,word比對準則的文字搜尋。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) 可讓您建立數種類型的對話方塊,包括訊息方塊、 通用對話方塊,以及自訂對話方塊。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訊息方塊是可用來顯示文字資訊,並允許使用者透過按鈕做出決定的對話方塊。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.

文書處理器對話方塊Word Processor dialog box

若要建立訊息方塊,您使用MessageBox類別。To create a message box, you use the MessageBox class. MessageBox 可讓您設定訊息方塊文字、 標題、 圖示和按鈕,使用如下所示的程式碼。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

若要顯示訊息方塊,請呼叫staticShow方法,如下列程式碼所示。To show a message box, you call the staticShow 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

如需有關如何使用訊息方塊的詳細資訊,請參閱 < MessageBoxMessageBox 範例,以及對話方塊範例For more information on using message boxes, see MessageBox, MessageBox Sample, and Dialog Box Sample.

雖然MessageBox可能會提供簡單的對話方塊方塊中的使用者經驗,使用的優點MessageBox就是唯一的可顯示由部分信任安全性沙箱內執行的應用程式的視窗類型 (請參閱安全性),例如XAML 瀏覽器應用程式 (XBAP)XAML browser applications (XBAPs)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 瀏覽器應用程式 (XBAP)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). 對於這些 Windows Presentation Foundation (WPF) 提供幾個通用對話方塊,並可讓您建立您自己的對話方塊中,雖然使用任一僅限於以完全信任執行的應用程式。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

WindowsWindows 實作所有應用程式通用之各種可重複使用的對話方塊,包括用於開啟檔案、儲存檔案和列印的對話方塊。 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) 會封裝開啟之檔案、 儲存檔案,並列印通用對話方塊和其公開為 managed 的類別,供您使用獨立應用程式中的資料。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.

開啟對話方塊Open dialog box

常見的 [開啟檔案] 對話方塊中會實作成OpenFileDialog類別,並位於Microsoft.Win32命名空間。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

如需有關 [開啟檔案] 對話方塊的詳細資訊,請參閱Microsoft.Win32.OpenFileDialogFor more information on the open file dialog box, see Microsoft.Win32.OpenFileDialog.

注意

OpenFileDialog 可以用來安全地擷取檔案名稱,以部分信任執行的應用程式 (請參閱安全性)。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.

另存新檔對話方塊Save As dialog box

儲存檔案 對話方塊中的一般會實作成SaveFileDialog類別,並位於Microsoft.Win32命名空間。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

如需詳細資訊,另存新檔 對話方塊中,請參閱Microsoft.Win32.SaveFileDialogFor more information on the save file dialog box, see Microsoft.Win32.SaveFileDialog.

如下圖所示,列印功能使用 [列印] 對話方塊,來選擇及設定使用者想要列印資料的目標印表機。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.

列印對話方塊Print dialog box

通用列印對話方塊會實作成PrintDialog類別,並位於System.Windows.Controls命名空間。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

如需有關 [列印] 對話方塊的詳細資訊,請參閱System.Windows.Controls.PrintDialogFor more information on the print dialog box, see System.Windows.Controls.PrintDialog. 如中列印的詳細討論WPFWPF,請參閱 < 列印概觀For detailed discussion of printing in WPFWPF, 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 實作這些行為,因此,您使用Window來建立自訂強制回應和非強制回應對話方塊。Window implements those behaviors and, consequently, you use Window to create custom modal and modeless dialog boxes.

建立自訂強制回應對話方塊Creating a Modal Custom Dialog Box

本主題說明如何使用Window來建立一般強制回應對話方塊方塊實作中,使用Margins對話方塊中,做為範例 (請參閱對話方塊範例)。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). Margins下圖顯示對話方塊。The Margins dialog box is shown in the following figure.

邊界對話方塊Margins dialog box

設定強制回應對話方塊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.

  • 顯示確定按鈕,使用者按一下以關閉對話方塊,返回函式,並繼續處理。Showing an OK button that users click to close the dialog box, return to the function, and continue processing.

  • 顯示取消使用者按一下以關閉對話方塊,然後停止進一步處理的函式的按鈕。Showing a Cancel button that users click to close the dialog box and stop the function from further processing.

  • 顯示關閉標題列中的按鈕。Showing a Close button in the title bar.

  • 顯示圖示。Showing an icon.

  • 顯示最小化最大化,並還原按鈕。Showing Minimize, Maximize, and Restore buttons.

  • 顯示系統功能表以最小化、 最大化、 還原及關閉對話方塊。Showing a System menu to minimize, maximize, restore, and close the dialog box.

  • 在開啟對話方塊的視窗上方和中央開啟。Opening above and in the center of the window that opened the dialog box.

  • 對話方塊的大小應該盡可能可供調整,以防止對話方塊過小,並提供使用者實用的預設大小,您必須分別設定預設大小和大小下限。Dialog boxes should be resizable where possible so, to prevent the dialog box from being too small, and to provide the user with a useful default size, you need to set both default and a minimum dimensions respectively.

  • 按下 ESC 鍵應該設定為的鍵盤快速鍵取消按鈕被按下。Pressing the ESC key should be configured as a keyboard shortcut that causes the Cancel button to be pressed. 這藉由設定來達成IsCancel的屬性取消按鈕以trueThis is achieved by setting the IsCancel property of the Cancel button to true.

  • 按下 ENTER (或 RETURN) 鍵應該設定為的鍵盤快速鍵確定按鈕被按下。Pressing the ENTER (or RETURN) key should be configured as a keyboard shortcut that causes the OK button to be pressed. 這藉由設定來達成IsDefault的屬性確定 按鈕trueThis is achieved 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
    {

Imports System
Imports System.ComponentModel
Imports System.Windows
Imports System.Windows.Controls
Imports Microsoft.Win32

Namespace SDKSample

Public Class MainWindow
    Inherits 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();

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 is passing default information (the current margins) to the dialog box. 它也會設定Window.Owner屬性會顯示對話方塊視窗的參考。It is also setting the Window.Owner property with a reference to the window that is showing the dialog box. 一般情況下,您應該一律設定 對話方塊中的擁有者,以提供視窗狀態相關行為通用於所有對話方塊 (請參閱WPF Windows 概觀如需詳細資訊)。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).

注意

您必須提供的擁有者才能支援使用者介面 (UI)user interface (UI)自動化對話方塊 (請參閱 < UI 自動化概觀)。You must provide an owner to support 使用者介面 (UI)user interface (UI) automation for dialog boxes (see UI Automation Overview).

設定對話方塊之後,它會顯示要強制藉由呼叫ShowDialog方法。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.

  • 從效能的觀點來看,多層式應用程式中的資料驗證可以減少用戶層與應用程式層之間的來回行程次數,特別是當應用程式是由 Web 服務或伺服器架構資料庫組成時。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.

若要驗證繫結的控制項中WPFWPF,您必須定義驗證規則,並將它與繫結產生關聯。To validate a bound control in WPFWPF, you need to define a validation rule and associate it with the binding. 驗證規則是自訂的類別衍生自ValidationRuleA validation rule is a custom class that derives from ValidationRule. 下列範例顯示的驗證規則, MarginValidationRule,繫結的值是用來檢查Double,並且在指定的範圍內。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

在這段程式碼,驗證規則的驗證邏輯會實作藉由覆寫Validate方法,它會驗證資料,並傳回適當ValidationResultIn 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>
    
<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>

驗證規則相關聯,一旦WPFWPF會自動將其套用的繫結控制項中輸入資料時。Once the validation rule is associated, WPFWPF will automatically apply it when data is entered into the bound control. 當控制項包含無效的資料,WPFWPF會顯示在無效的控制項周圍的紅色框線,如下圖所示。When a control contains invalid data, WPFWPF will display a red border around the invalid control, as shown in the following figure.

無效的左邊界Invalid left margin

在使用者輸入有效的資料之前,WPFWPF 不會將使用者侷限在無效的控制項。WPFWPF 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. 基於這個理由,您的程式碼也需要驗證對話方塊中的所有控制項時 [確定] 藉由處理按下按鈕Click事件。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
    {
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Input

Namespace SDKSample


Public Class MarginsDialogBox
    Inherits Window
void okButton_Click(object sender, RoutedEventArgs e)
{
    // Don't accept the dialog box if there is invalid data
    if (!IsValid(this)) return;
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
        }

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

此程式碼會列舉視窗上的所有相依性物件,如果有任何無效 (所傳回GetHasError,在無效的控制項取得焦點,IsValid方法會傳回false,和視窗會視為無效。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

開啟對話方塊方塊中,使用ShowDialog基本上就像是呼叫方法: 開啟對話方塊方塊中,使用的程式碼ShowDialog等到ShowDialog傳回。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. ShowDialog傳回,程式碼需要呼叫它來決定是否要繼續處理還是停止處理,根據使用者所按下確定 按鈕或取消 按鈕。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. 為了簡化這項決定,對話方塊必須傳回做為使用者選擇Boolean會從傳回的值ShowDialog方法。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.

[確定] 按一下按鈕時,ShowDialog應該會傳回trueWhen the OK button is clicked, ShowDialog should return true. 這藉由設定來達成DialogResult屬性對話方塊的方塊時 [確定] 按一下按鈕時。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
    {
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Input

Namespace SDKSample


Public Class MarginsDialogBox
    Inherits Window
void okButton_Click(object sender, RoutedEventArgs e)
{
Private Sub okButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
    // Dialog box accepted
    this.DialogResult = true;
}
    ' Dialog box accepted
    MyBase.DialogResult = New Nullable(Of Boolean)(True)
End Sub
    }
}
End Class

End Namespace

請注意,設定DialogResult屬性也會使視窗自動關閉,而不需要明確呼叫CloseNote that setting the DialogResult property also causes the window to close automatically, which alleviates the need to explicitly call Close.

取消按一下按鈕時,ShowDialog應該會傳回false,也需要設定DialogResult屬性。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
    {
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Input

Namespace SDKSample


Public Class MarginsDialogBox
    Inherits Window
void cancelButton_Click(object sender, RoutedEventArgs e)
{
    // Dialog box canceled
    this.DialogResult = false;
}
Private Sub cancelButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
    ' Dialog box canceled
    Me.DialogResult = False
End Sub
    }
}
End Class

End Namespace

當按鈕的IsCancel屬性設定為true且使用者按下其中一個取消 按鈕或 ESC 鍵時,DialogResult會自動設為falseWhen 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. 下列標記有上述的程式碼,而不需要處理相同的效果Click事件。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>

對話方塊會自動傳回false當使用者按下關閉按鈕的標題列中,或選擇關閉功能表項目從System功能表。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

DialogResult設定的對話方塊中,開啟它的函式可以藉由檢查取得對話方塊結果DialogResult屬性時ShowDialog傳回。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
    {

Imports System
Imports System.ComponentModel
Imports System.Windows
Imports System.Windows.Controls
Imports Microsoft.Win32

Namespace SDKSample

Public Class MainWindow
    Inherits Window
void formatMarginsMenuItem_Click(object sender, RoutedEventArgs e)
{
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 == true)
    {
        // Update fonts
        this.documentTextBox.Margin = dlg.DocumentMargin;
    }
}
    ' 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

如果對話方塊結果為true,函式,做為提示來擷取及處理使用者所提供的資料。If the dialog result is true, the function uses that as a cue to retrieve and process the data provided by the user.

注意

之後ShowDialog已經傳回,無法重新開啟對話方塊。After ShowDialog has returned, a dialog box cannot be reopened. 您必須改為建立新的執行個體。Instead, you need to create a new instance.

如果對話方塊結果為false,函式應該適當地結束處理。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.

尋找對話方塊Find dialog box

不過,其行為稍有不同,如下列各節中所述。However, the behavior is slightly different, as described in the following sections.

開啟非強制回應對話方塊Opening a Modeless Dialog Box

藉由呼叫開啟非強制回應對話方塊Show方法。A modeless dialog box is opened by calling the Show method.

<!--Main Window-->
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Win32;

namespace SDKSample
{
    public partial class MainWindow : Window
    {

Imports System
Imports System.ComponentModel
Imports System.Windows
Imports System.Windows.Controls
Imports Microsoft.Win32

Namespace SDKSample

Public Class MainWindow
    Inherits 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();
}
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

不同於ShowDialogShow會立即傳回。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

在此範例中,FindDialogBox可能會傳回一或多個找到的主視窗中,根據的文字,而不需要任何特定的頻率所搜尋的結果。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 實作TextFoundEvent基於此目的,因此首先需要委派。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

使用TextFoundEventHandler委派,請FindDialogBox實作TextFoundEventUsing 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
Imports System.Windows
Imports System.Windows.Controls
Imports System.Text.RegularExpressions

Namespace SDKSample

Public Class FindDialogBox
    Inherits Window
    Public Event TextFound As TextFoundEventHandler
    Protected Overridable Sub OnTextFound()
        RaiseEvent TextFound(Me, EventArgs.Empty)
    End Sub
    }
}
End Class

End Namespace

因此,Find可以引發事件時找到搜尋結果。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
    {
Imports System
Imports System.Windows
Imports System.Windows.Controls
Imports System.Text.RegularExpressions

Namespace SDKSample

Public Class FindDialogBox
    Inherits Window
void findNextButton_Click(object sender, RoutedEventArgs e)
{
Private Sub findNextButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
// Text found
this.index = match.Index;
this.length = match.Length;
OnTextFound();
Me.Index = match.Index
Me.Length = match.Length
RaiseEvent TextFound(Me, EventArgs.Empty)
}
End Sub
    }
}
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
    {

Imports System
Imports System.ComponentModel
Imports System.Windows
Imports System.Windows.Controls
Imports Microsoft.Win32

Namespace SDKSample

Public Class MainWindow
    Inherits 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();
        }
    }
}
    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

因為DialogResult不需要進行設定,可以關閉非強制回應對話方塊,使用系統提供的機制,包括下列: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.

  • 按下 ALT+F4。Pressing ALT+F4.

  • 選擇關閉系統功能表。Choosing Close from the System menu.

或者,您的程式碼可以呼叫Close關閉按一下按鈕時。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
    {
Imports System
Imports System.Windows
Imports System.Windows.Controls
Imports System.Text.RegularExpressions

Namespace SDKSample

Public Class FindDialogBox
    Inherits Window
        void closeButton_Click(object sender, RoutedEventArgs e)
        {
            // Close dialog box
            this.Close();
        }
    }
}
    Private Sub closeButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
        MyBase.Close()
    End Sub
End Class

End Namespace

另請參閱See Also

快顯功能表概觀Popup Overview
對話方塊範例Dialog Box Sample
ColorPicker Custom Control Sample (ColorPicker 自訂控制項範例)ColorPicker Custom Control Sample