對話方塊概觀

獨立應用程式通常會有主視窗,這兩者都會顯示應用程式運作的主要資料,並公開功能,以透過使用者介面 (UI) 機制來處理該資料,例如功能表列、工具列和狀態列。 重要的應用程式還可能顯示其他視窗來執行下列動作:

  • 對使用者顯示特定資訊。

  • 向使用者收集資訊。

  • 顯示並收集資訊。

這種視窗稱為「對話方塊」,可分為兩種類型︰強制回應和非強制回應。

當某個函式需要使用者提供其他資料才能繼續時,該函式會顯示「強制回應」對話方塊。 由於該函式需要透過強制回應對話方塊收集資料,因此當強制回應對話方塊保持開啟時,也可以防止使用者在應用程式中啟動其他視窗。 在大多數情況下,強制回應對話方塊可讓使用者藉由按下 [確定] 或 [取消] 按鈕,指出完成強制回應對話方塊。 按下 [確定] 按鈕表示使用者已輸入資料,並且希望此函式繼續處理該資料。 按下 [取消] 按鈕表示使用者想要完全停止執行此函式。 強制回應對話方塊的最常見範例為開啟、儲存及列印資料。

另一方面,「非強制回應」對話方塊在開啟時,不會防止使用者啟動其他視窗。 例如,如果使用者想要尋找出現在文件中的特定字組,主視窗通常會開啟對話方塊,詢問使用者要尋找哪個字組。 不過,由於尋找字組並不會防止使用者編輯文件,因此對話方塊不需要是強制回應。 非強制回應對話方塊至少會提供 [關閉] 按鈕以關閉對話方塊,並可能會提供其他按鈕以執行特定函式,例如 [尋找下一個] 按鈕以尋找下一個符合字組搜尋準則的字組。

Windows Presentation Foundation (WPF) 可讓您建立數種類型的對話方塊,包括訊息方塊、通用對話方塊和自訂對話方塊。 本主題將討論每種類型,而 Dialog Box Sample (對話方塊範例) 將提供相符的範例。

訊息方塊

「訊息方塊」是可用來顯示文字資訊,並讓使用者透過按鈕做出決定的對話方塊。 下圖所示的訊息方塊顯示文字資訊、提出問題,並提供使用者三個按鈕來回答問題。

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

若要建立訊息方塊,您可以使用 類別 MessageBoxMessageBox 可讓您使用如下所示的程式碼來設定訊息方塊文字、標題、圖示和按鈕。

// 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 方法,如下列程式碼所示。

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

當顯示訊息方塊的程式碼必須偵測及處理使用者的決定時 (按下哪個按鈕),程式碼可以查看訊息方塊結果,如下列程式碼所示。

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

如需使用訊息方塊的詳細資訊,請參閱 MessageBox MessageBox 範例 對話方塊範例

雖然 MessageBox 可能會提供簡單的對話方塊使用者體驗,但使用 MessageBox 的優點是,這是在部分信任安全性沙箱內執行的應用程式唯一可以顯示的視窗類型(請參閱 安全性 ),例如 XAML 瀏覽器應用程式(XBAP)。

大多數對話方塊所顯示及收集的資料會比訊息方塊的結果更複雜,包括文字、選取範圍 (核取方塊)、互斥選取範圍 (選項按鈕),以及清單選取範圍 (清單方塊、下拉式方塊、下拉式清單方塊)。 針對這些情況,Windows Presentation Foundation (WPF) 提供數個常見的對話方塊,並可讓您建立自己的對話方塊,不過使用任一個都僅限於完全信任執行的應用程式。

一般對話方塊

Windows 會實作所有應用程式通用的各種可重複使用對話方塊,包括開啟檔案、儲存檔案和列印的對話方塊。 由於這些對話方塊是由作業系統實作,因此可在作業系統上執行的所有應用程式之間共用,以協助確保使用者體驗的一致性;當使用者在一個應用程式中熟悉如何使用某個作業系統提供的對話方塊時,就不需要了解如何在其他應用程式中使用該對話方塊。 因為這些對話方塊可供所有應用程式使用,並協助提供一致的使用者體驗,所以稱為「通用對話方塊」

Windows Presentation Foundation (WPF) 封裝開啟的檔案、儲存檔案和列印通用對話方塊,並將它們公開為受控類別,讓您在獨立應用程式中使用。 本主題提供每個對話方塊的簡短概觀。

開啟 [檔案] 對話方塊

如下圖所示,檔案開啟功能使用 [開啟檔案] 對話方塊,來擷取要開啟之檔案的名稱。

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

通用開啟的檔案對話方塊會實作為 類別, OpenFileDialog 且位於 命名空間中 Microsoft.Win32 。 下列程式碼示範如何建立、設定及顯示一個對話方塊,以及如何處理結果。

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

注意

OpenFileDialog 可用於透過部分信任執行的應用程式安全地擷取檔案名(請參閱 安全性 )。

儲存對話方塊

如下圖所示,檔案儲存功能使用 [儲存檔案] 對話方塊,來擷取要儲存之檔案的名稱。

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

通用儲存檔案對話方塊會實作為 SaveFileDialog 類別,且位於 命名空間中 Microsoft.Win32 。 下列程式碼示範如何建立、設定及顯示一個對話方塊,以及如何處理結果。

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

如下圖所示,列印功能使用 [列印] 對話方塊,來選擇及設定使用者想要列印資料的目標印表機。

Screenshot that shows a Print dialog box.

通用列印對話方塊會實作為 PrintDialog 類別,且位於 命名空間中 System.Windows.Controls 。 下列程式碼示範如何建立、設定及顯示一個對話方塊。

// 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.PrintDialog 。 如需 WPF 中列印的詳細討論,請參閱 列印概觀

自訂對話方塊

雖然通用對話方塊很有用,而且應該盡可能使用,但這類對話方塊並不支援定義域專屬對話方塊的需求。 在此情況下,您必須建立自己的對話方塊。 如稍後所示,對話方塊是具有特殊行為的視窗。 Window 會實作這些行為,因此,您可以使用 Window 來建立自訂強制回應和無強制回應對話方塊。

建立強制回應自訂對話方塊

本主題示範如何使用 Window 對話方塊作為範例來建立一般強制回應對話方塊實 Margins 作(請參閱 對話方塊範例 )。 Margins下圖顯示對話方塊。

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

設定強制回應對話方塊

一般對話方塊的使用者介面包括:

  • 收集想要的資料所需的各種控制項。

  • 使用者按一下以關閉對話方塊、返回函式,並繼續處理的 [確定 ] 按鈕。

  • 使用者 按一下以關閉對話方塊並停止函式進一步處理的 [取消 ] 按鈕。

  • 標題列中的 [關閉 ] 按鈕。

  • 圖示。

  • 最小化 最大化 還原 按鈕。

  • 系統 功能表,可將對話方塊最小化、最大化、還原及關閉。

  • 開啟對話方塊之視窗中央和上方的位置。

  • 能夠盡可能調整大小,以防止對話方塊太小,並為使用者提供有用的預設大小。 這需要您同時設定預設值和最小維度。

  • ESC 鍵做為鍵盤快速鍵,導致 按下 [取消 ] 按鈕。 您可以將 [取消 ] 按鈕的 屬性設定 IsCanceltrue ,以執行此動作。

  • ENTER (或 RETURN) 鍵做為鍵盤快速鍵,導致 按下 [確定 ] 按鈕。 您可以藉由設定 IsDefault [確定 ] 按鈕 true 屬性來執行此動作。

下列程式碼示範這項設定。

<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

對話方塊的使用者體驗也會延伸至開啟對話方塊之視窗的功能表列。 當功能表項目所執行的函式需要透過對話方塊進行使用者互動才能繼續時,該函式的功能表項目會在其標頭中顯示省略符號,如下所示。

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

當功能表項目所執行的函式顯示不需要使用者互動的對話方塊時 (例如 [關於] 對話方塊),則不需要省略符號。

開啟強制回應對話方塊

對話方塊通常是使用者選取功能表項目以執行定義域專屬函式所顯示的結果,例如在文書處理器中設定文件的邊界。 將視窗顯示為對話方塊類似於顯示標準視窗,不過需要進行額外的對話方塊專屬設定。 具現化、設定及開啟對話方塊的整個過程如下列程式碼所示。

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

在這裡,程式碼會將預設資訊(目前邊界)傳遞給對話方塊。 它也會使用顯示對話方塊之視窗的參考來設定 Window.Owner 屬性。 一般而言,您一律必須設定對話方塊的主控視窗,以提供所有對話方塊通用的視窗狀態相關行為 (如需詳細資訊,請參閱 WPF 視窗概觀)。

注意

您必須提供擁有者來支援對話方塊的使用者介面(UI) 自動化(請參閱 消費者介面自動化概觀 )。

設定對話方塊之後,呼叫 方法會以 ShowDialog 強制回應方式顯示對話方塊。

驗證使用者提供的資料

在開啟對話方塊且使用者提供所需資料之後,對話方塊會基於下列原因負責確保提供的資料有效:

  • 從安全性的觀點來看,應該驗證所有輸入。

  • 從定義域專屬的觀點來看,資料驗證可以防止程式碼處理錯誤的資料,這可能會擲回例外狀況。

  • 從使用者體驗的觀點來看,對話方塊可藉由對使用者顯示哪些輸入的資料無效來協助使用者。

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

若要驗證 WPF 中的繫結控制項,您必須定義驗證規則,並將它與系結產生關聯。 驗證規則是衍生自 ValidationRule 的自訂類別。 下列範例示範驗證規則 , MarginValidationRule 它會檢查系結值是否為 Double ,且位於指定的範圍內。

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 方法來實作,此方法會驗證資料並傳回適當的 ValidationResult

若要建立驗證規則與繫結控制項的關聯,您可以使用下列標記。

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

一旦驗證規則相關聯,WPF 就會在資料輸入繫結控制項時自動套用它。 當控制項包含不正確資料時,WPF 會在不正確控制項周圍顯示紅色框線,如下圖所示。

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

WPF 在使用者輸入有效資料之前,不會將使用者限制為不正確控制項。 這是很好的對話方塊行為;使用者應該能夠自由地巡覽對話方塊中的控制項,而不論資料是否有效。 不過,這表示使用者可以輸入無效的資料並按下 [確定] 按鈕。 基於這個理由,當處理 Click 事件按下 [確定 ] 按鈕時 ,您的程式碼也需要驗證對話方塊中的所有控制項。

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

此程式碼會列舉視窗上的所有相依性物件,如果有任何相依性物件無效,則無效 GetHasError 的控制項會取得焦點, IsValid 方法會 false 傳回 ,而且視窗視為無效。

一旦對話方塊有效,就可以安全地將它關閉並傳回。 在傳回過程中,必須將結果傳回呼叫函式。

設定強制回應對話方塊結果

使用 ShowDialog 開啟對話方塊基本上就像呼叫 方法:使用 ShowDialog 等候直到傳回時 ShowDialog 開啟對話方塊的程式碼。 傳回時 ShowDialog ,呼叫它的程式碼必須根據使用者 按下 [確定 ] 按鈕或 [取消 ] 按鈕,決定是否要繼續處理或 停止處理。 為了方便此決策,對話方塊必須傳回使用者的選擇做為 BooleanShowDialog 方法傳回的值。

按一下 [ 確定] 按鈕時, ShowDialog 應該會傳回 true 。 按一下 [確定 ] 按鈕時 ,設定對話方塊的 屬性即可達成 DialogResult 此目的。

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

請注意,設定 DialogResult 屬性也會讓視窗自動關閉,這可減輕明確呼叫 Close 的需求。

按一下 [ 取消] 按鈕時, ShowDialog 應該會傳回 false ,這也需要設定 DialogResult 屬性。

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

當按鈕的 IsCancel 屬性設定為 true ,且使用者按下 [取消 ] 按鈕或 ESC 鍵時, DialogResult 會自動設定為 false 。 下列標記的效果與上述程式碼相同,而不需要處理 Click 事件。

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

當使用者按下標題列中的 [關閉] 按鈕,或從 [系統 ] 功能表中選擇 [關閉 ] 功能表項目時,對話方塊會自動傳回 false

處理從強制回應對話方塊傳回的資料

當 由對話方塊設定時 DialogResult ,開啟它的函式可以藉由在傳回時 ShowDialog 檢查 DialogResult 屬性來取得對話方塊結果。

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

如果對話方塊結果為 true,此函式會使用該值作為提示,以擷取及處理使用者提供的資料。

注意

傳回之後 ShowDialog ,就無法重新開啟對話方塊。 您必須改為建立新的執行個體。

如果對話方塊結果為 false,此函式應該適當地結束處理。

建立無模式自訂對話方塊

非強制回應對話方塊 (例如下圖所示的 [尋找] 對話方塊) 與強制回應對話方塊具有相同的基本外觀。

Screenshot that shows a Find dialog box.

不過,其行為稍有不同,如下列各節中所述。

開啟無強制回應對話方塊

呼叫 方法會開啟 Show 無強制回應對話方塊。

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

不同于 ShowDialogShow 會立即傳回 。 因此,呼叫視窗無法得知非強制回應對話方塊何時關閉,因此不會知道何時要檢查對話方塊結果,或從對話方塊取得資料以進一步處理。 相反地,對話方塊必須建立其他方式,以將資料傳回呼叫視窗進行處理。

處理從無強制回應對話方塊傳回的資料

在此範例中, FindDialogBox 可能會根據搜尋的文字而將一或多個尋找結果傳回至主視窗,而不需要任何特定頻率。 如同強制回應對話方塊,非強制回應對話方塊可以透過屬性傳回結果。 不過,主控對話方塊的視窗必須知道何時要查看這些屬性。 其中一個做法是,讓對話方塊實作每次找到文字時所引發的事件。 FindDialogBoxTextFoundEvent 針對此目的實作 ,其首先需要委派。

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 實作 TextFoundEvent

using System;
using System.Windows;
using System.Windows.Controls;
using System.Text.RegularExpressions;

namespace SDKSample
{
    public partial class FindDialogBox : Window
    {
        public event TextFoundEventHandler TextFound;

        protected virtual void OnTextFound()
        {
            TextFoundEventHandler textFound = this.TextFound;
            if (textFound != null) textFound(this, EventArgs.Empty);
        }

    }
}
Imports System.Windows
Imports System.Windows.Controls
Imports System.Text.RegularExpressions

Namespace SDKSample

    Public Class FindDialogBox
        Inherits Window

        Public Event TextFound As TextFoundEventHandler

        Protected Overridable Sub OnTextFound()
            RaiseEvent TextFound(Me, EventArgs.Empty)
        End Sub

    End Class
End Namespace

因此,當找到搜尋結果時, Find 可能會引發 事件。

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

主控視窗接著需要註冊及處理此事件。

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

關閉無強制回應對話方塊

因為 DialogResult 不需要設定,因此可以使用系統提供機制來關閉無強制回應對話方塊,包括下列專案:

  • 按一下標題列中的 [關閉] 按鈕。

  • 按下 ALT+F4。

  • [系統] 功能表選擇 [關閉 ]。

或者,按一下 [關閉 ] 按鈕時 ,您的程式碼可以呼叫 Close

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

另請參閱