共用方式為


對話框概觀 (WPF.NET)

Windows Presentation Foundation (WPF) 可讓您設計自己的對話方塊。 對話框是視窗,但具有特定意圖和用戶體驗。 本文討論對話框的運作方式,以及您可以建立及使用的對話框類型。 對話框可用來:

  • 對使用者顯示特定資訊。
  • 向使用者收集資訊。
  • 顯示並收集資訊。
  • 顯示操作系統提示字元,例如列印視窗。
  • 選取檔案或資料夾。

這些類型的視窗稱為 對話框。 對話框可以透過兩種方式顯示:強制回應和無模式。

向使用者顯示強制回應對話框是一種技術,應用程式會在使用者關閉對話方塊之前中斷其所執行的動作。 這通常以提示或警示的形式出現。 在關閉對話方塊之前,應用程式中的其他視窗無法與其互動。 關閉強制回應對話框之後,應用程式就會繼續。 最常見的對話框是用來顯示開啟的檔案或儲存盤案提示、顯示印表機對話框,或傳訊使用者的某些狀態。

模式對話框不會防止用戶在開啟時啟動其他視窗。 例如,如果使用者想要在檔中尋找特定單字的出現次數,主視窗通常會開啟對話框,詢問用戶他們正在尋找哪一個字。 由於應用程式不想防止使用者編輯檔,因此對話方塊不需要強制回應。 無模式對話框至少會提供關閉 對話方塊的 [關閉 ] 按鈕。 您可以提供其他按鈕來執行特定功能,例如 [尋找下一步] 按鈕,以在文字搜尋中尋找下一個單字。

透過 WPF,您可以建立數種類型的對話方塊,例如消息框、通用對話框和自定義對話框。 本文將討論每個範例,而 對話框範例會提供比對 範例。

訊息方塊

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

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

若要建立消息框,您可以使用 類別 MessageBoxMessageBox 可讓您設定消息框文字、標題、圖示和按鈕。

如需詳細資訊,請參閱 如何開啟消息框

一般對話框

Windows 會實作所有應用程式通用的各種可重複使用對話方塊,包括用於選取檔案和列印的對話方塊。

由於這些對話框是由作業系統所提供,所以這些對話框會在作業系統上執行的所有應用程式之間共用。 這些對話框提供一致的用戶體驗,稱為 通用對話方塊。 當使用者在一個應用程式中使用通用對話框時,他們不需要瞭解如何在其他應用程式中使用該對話方塊。

WPF 會封裝開啟的檔案、儲存盤案、開啟資料夾,並列印通用對話方塊,並將它們公開為受控類別以供您使用。

Open file dialog box called from WPF.

若要深入瞭解一般對話框,請參閱下列文章:

自訂對話框

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

當您建立自己的對話框時,需要考慮許多設計考慮。 雖然應用程式視窗和對話框都包含相似之處,例如共用相同的基類,但對話框會用於特定用途。 當您需要提示使用者輸入某種資訊或回應時,通常需要對話框。 一般而言,當對話框 (強制回應) 顯示時,應用程式會暫停,限制對應用程式其餘部分的存取。 一旦對話框關閉,應用程式就會繼續。 不過,將互動限制在對話方塊本身並不是必要專案。

當 WPF 視窗關閉時,就無法重新開啟。 自定義對話框是 WPF 視窗,而且會套用相同的規則。 若要瞭解如何關閉視窗,請參閱 如何關閉視窗或對話框

實作對話方塊

設計對話框時,請遵循下列建議來建立良好的用戶體驗:

❌ 不要雜亂顯示對話框視窗。 對話框體驗是讓使用者輸入某些數據,或做出選擇。

✔️ 請提供 [確定] 按鈕來關閉視窗。

✔️ 請設定 [確定 ] 按鈕的 IsDefault 屬性 true ,讓使用者按下 ENTER 鍵以接受並關閉視窗。

✔️ 請考慮新增 [ 取消] 按鈕,讓使用者可以關閉視窗,並指出他們不想繼續。

✔️ DO 將 [ 取消 ] 按鈕的 IsCancel 屬性設定為 true ,讓使用者按下 ESC 鍵關閉視窗。

✔️ DO 會設定視窗的標題,以正確描述對話代表的內容,或使用者應該對對話框執行的動作。

✔️ 請設定視窗的最小寬度和高度值,以防止使用者調整視窗的大小太小。

✔️ 如果 ShowInTaskbar 設定為 false,請考慮停用調整視窗大小的能力。 您可以藉由將 設定 ResizeMode 為 來停用重設大小 NoResize

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

<Window x:Class="Dialogs.Margins"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Change Margins"
        Closing="Window_Closing"
        MinHeight="200"
        MinWidth="300"
        SizeToContent="WidthAndHeight"
        ResizeMode="NoResize"
        ShowInTaskbar="False"
        WindowStartupLocation="CenterOwner" 
        FocusManager.FocusedElement="{Binding ElementName=leftMarginTextBox}">
    <Grid Margin="10">
        <Grid.Resources>
            <!-- Default settings for controls -->
            <Style TargetType="{x:Type Label}">
                <Setter Property="Margin" Value="0,3,5,5" />
                <Setter Property="Padding" Value="0,0,0,5" />
            </Style>
            <Style TargetType="{x:Type TextBox}">
                <Setter Property="Margin" Value="0,0,0,5" />
            </Style>
            <Style TargetType="{x:Type Button}">
                <Setter Property="Width" Value="70" />
                <Setter Property="Height" Value="25" />
                <Setter Property="Margin" Value="5,0,0,0" />
            </Style>
        </Grid.Resources>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition />
        </Grid.RowDefinitions>

        <!-- Left,Top,Right,Bottom margins-->
        <Label Grid.Column="0" Grid.Row="0">Left Margin:</Label>
        <TextBox Name="leftMarginTextBox" Grid.Column="1" Grid.Row="0" />

        <Label Grid.Column="0" Grid.Row="1">Top Margin:</Label>
        <TextBox Name="topMarginTextBox" Grid.Column="1" Grid.Row="1"/>

        <Label Grid.Column="0" Grid.Row="2">Right Margin:</Label>
        <TextBox Name="rightMarginTextBox" Grid.Column="1" Grid.Row="2" />

        <Label Grid.Column="0" Grid.Row="3">Bottom Margin:</Label>
        <TextBox Name="bottomMarginTextBox" Grid.Column="1" Grid.Row="3" />

        <!-- Accept or Cancel -->
        <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="4" Orientation="Horizontal" HorizontalAlignment="Right">
            <Button Name="okButton" Click="okButton_Click" IsDefault="True">OK</Button>
            <Button Name="cancelButton" IsCancel="True">Cancel</Button>
        </StackPanel>
    </Grid >
</Window>

上述 XAML 會建立類似下圖的視窗:

A dialog box window for WPF that shows left, top, right, bottom text boxes.

開啟對話框的UI元素

對話框的用戶體驗也會延伸到開啟對話框的功能表列或按鈕。 當功能表項或按鈕執行函式,該函式需要使用者透過對話框進行互動,然後函式才能繼續執行時,控件應該在其標頭文字的結尾使用省略號:

<MenuItem Header="_Margins..." Click="formatMarginsMenuItem_Click" />
<!-- or -->
<Button Content="_Margins..." Click="formatMarginsButton_Click" />

當功能表項或按鈕執行函式時,顯示不需要使用者互動的對話框,例如 [關於] 對話框,則不需要省略號。

功能表項是為使用者提供應用程式動作的常見方式,這些動作會分組為相關主題。 您可能已在許多不同的應用程式上看到 [ 檔案 ] 功能表。 在一般應用程式中,[ 檔案 ] 功能表項提供儲存盤案、載入檔案及列印檔案的方式。 如果動作要顯示強制回應視窗,標頭通常會包含省略號,如下圖所示:

A WPF window that shows menu items with an ellipsis to indicate which item shows a dialog box.

其中兩個功能表項有省略號: ...。 這有助於使用者識別當他們選取這些功能表項時,會顯示強制回應窗口,暫停應用程式,直到使用者關閉它為止。

此設計技術是一種簡單的方式,可讓您與使用者溝通他們應該預期的內容。

按鈕

您可以遵循功能表項一節中所述的相同原則。 使用按鈕文字上的省略號,指出當使用者按下按鈕時,會出現強制回應對話方塊。 在下圖中,有兩個按鈕,而且很容易了解哪個按鈕會顯示對話框:

A WPF window that shows buttons with an ellipsis to indicate which item shows a dialog box.

傳回結果

開啟另一個視窗,特別是強制回應對話框,是傳回狀態和呼叫程式碼資訊的絕佳方式。

呼叫 來顯示 ShowDialog()對話框時,開啟對話框的程式代碼會等到 ShowDialog 方法傳回為止。 方法傳回時,呼叫它的程式代碼必須決定是否要繼續處理或停止處理。 使用者通常會在對話框上按 [確定] 或 [取消] 按鈕來指出這一點。

按下 [確定] 按鈕時,ShowDialog應該設計為傳回 true,而 [取消] 按鈕則傳回 false。 這是藉由在按下按鈕時設定 DialogResult 屬性來達成。

private void okButton_Click(object sender, RoutedEventArgs e) =>
    DialogResult = true;

private void cancelButton_Click(object sender, RoutedEventArgs e) =>
    DialogResult = false;
Private Sub okButton_Click(sender As Object, e As RoutedEventArgs)
    DialogResult = True
End Sub

Private Sub cancelButton_Click(sender As Object, e As RoutedEventArgs)
    DialogResult = False
End Sub

DialogResult只有當對話框以 顯示ShowDialog()時,才能設定 屬性。 設定 屬性 DialogResult 時,對話框會關閉。

如果按鈕的 IsCancel 屬性設定為 true,而且視窗會以 ShowDialog()開啟, ESC 鍵會關閉視窗並設定 DialogResultfalse

如需關閉對話框的詳細資訊,請參閱 如何關閉視窗或對話框

處理回應

ShowDialog() 傳回布爾值,指出使用者是否接受或取消對話框。 如果您要向使用者發出警示,但不需要他們做出決策或提供數據,您可以忽略回應。 您也可以檢查 DialogResult 屬性來檢查回應。 下列程式代碼示範如何處理回應:

var dialog = new Margins();

// Display the dialog box and read the response
bool? result = dialog.ShowDialog();

if (result == true)
{
    // User accepted the dialog box
    MessageBox.Show("Your request will be processed.");
}
else
{
    // User cancelled the dialog box
    MessageBox.Show("Sorry it didn't work out, we'll try again later.");
}
Dim marginsWindow As New Margins

Dim result As Boolean? = marginsWindow.ShowDialog()

If result = True Then
    ' User accepted the dialog box
    MessageBox.Show("Your request will be processed.")
Else
    ' User cancelled the dialog box
    MessageBox.Show("Sorry it didn't work out, we'll try again later.")
End If

marginsWindow.Show()

無模式對話框

若要顯示對話框無模式,請呼叫 Show()。 對話框至少應該提供 [關閉] 按鈕。 您可以提供其他按鈕和互動式元素來執行特定函式,例如 [尋找下 一步] 按鈕,以在文字搜尋中尋找下一個單字。

因為無模式對話框不會封鎖呼叫程式代碼繼續,所以您必須提供不同的傳回結果方式。 您可以執行下列其中一個步驟:

  • 在視窗上公開資料物件屬性。
  • Window.Closed處理呼叫程式代碼中的事件。
  • 在用戶選取物件或按下特定按鈕時引發的視窗上建立事件。

下列範例會 Window.Closed 使用 事件,在對話框關閉時向用戶顯示消息框。 顯示的訊息會參考關閉對話框的屬性。 如需關閉對話框的詳細資訊,請參閱 如何關閉視窗或對話框

var marginsWindow = new Margins();

marginsWindow.Closed += (sender, eventArgs) =>
{
    MessageBox.Show($"You closed the margins window! It had the title of {marginsWindow.Title}");
};

marginsWindow.Show();
Dim marginsWindow As New Margins

AddHandler marginsWindow.Closed, Sub(sender As Object, e As EventArgs)
                                     MessageBox.Show($"You closed the margins window! It had the title of {marginsWindow.Title}")
                                 End Sub

marginsWindow.Show()

另請參閱