WPF 視窗概觀 (WPF .NET)

使用者透過視窗與 Windows Presentation Foundation (WPF) 應用程式互動。 視窗的主要用途是裝載內容,以視覺化方式檢視資料,並讓使用者可以與資料互動。 WPF 應用程式使用 Window 類別提供獨家視窗。 本文會先介紹 Window,再討論建立與管理應用程式視窗的基本概念。

重要

本文使用從 C# 專案產生的 XAML。 如果您使用的是 Visual Basic,那麼 XAML 看起來可能略有不同。 這些差異通常會出現在 x:Class 屬性值上。 C# 包含專案的根命名空間,但 Visual Basic 則不包含。

C# 專案範本建立的 App 類型是包含在 app.xaml 檔案中。 此類型在 Visual Basic 中名為 Application,檔案則名為 Application.xaml

Window 類別

在 WPF 中,視窗是由 Window 類別封裝,您可以用來執行下列動作:

  • 顯示視窗。
  • 設定視窗的大小、位置和外觀。
  • 裝載應用程式特定內容。
  • 管理視窗的存留期。

下圖說明視窗的組成部分:

Screenshot that shows parts of a WPF window.

視窗分為兩個區域︰非工作區和工作區。

視窗的「非工作區」由 WPF 實作,並且包含大多數視窗通用的視窗組件,包括:

  • 標題列 (1-5)。
  • 圖示 (1)。
  • 標題 (2)。
  • 最小化 (3)、最大化 (4) 和關閉 (5) 按鈕。
  • 包含功能表項目的系統功能表 (6)。 按一下圖示時即會出現 (1)。
  • 框線 (7)。

視窗「工作區」是視窗非工作區中的區域,供開發人員新增應用程式特定的內容,例如功能表列、工具列和控制項。

  • 工作區 (8)。
  • 調整大小底框 (9)。 這是新增至工作區 (8) 的控制項。

實作視窗

典型視窗的實作包括外觀和行為,其中「外觀」定義視窗呈現給使用者的樣貌,而「行為」則定義當使用者與視窗互動時的視窗運作方式。 在 WPF 中,您可以使用程式碼或 XAML 標記實作視窗的外觀和行為。

不過,一般而言,視窗的外觀是使用 XAML 標記實作,其行為則使用程式碼後置來實作,如下列範例所示。

<Window x:Class="WindowsOverview.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WindowsOverview"
        >

    <!-- Client area containing the content of the window -->
    
</Window>

下列程式碼是 XAML 的程式碼後置。

using System.Windows;

namespace WindowsOverview
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }
    }
}
Public Class Window1

End Class

若要讓 XAML 標記檔案和程式碼後置檔案能一起運作,需要下列各項:

  • 在標記中,Window 元素必須包含 x:Class 屬性。 建置應用程式時,x:Class 屬性會讓 Microsoft Build Engine (MSBuild) 產生 partial 類別,此類別衍生自 Window,名稱為 x:Class 屬性所指定。 這需要新增 XAML 結構描述的 XML 命名空間宣告 (xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml")。 所產生的 partial 類別會實作 InitializeComponent 方法,註冊事件及設定標記中的實作屬性時會呼叫此類別。

  • 在程式碼後置中,此類別必須是具有標記中 x:Class 屬性所指定之相同名稱的 partial 類別,而且必須衍生自 Window。 這可讓程式碼後置檔案建立與建置應用程式時由標記檔案所產生之 partial 類別的關聯,如需詳細資訊,請參閱編譯 WPF 應用程式

  • 在程式碼後置中,Window 類別必須實作呼叫 InitializeComponent 方法的建構函式。 標記檔案產生的 partial 類別實作 InitializeComponent,以登錄事件,並設定在標記中定義的屬性。

注意

當您使用 Visual Studio 將新的 Window 新增至專案時,會使用標記和程式碼後置實作 Window,而其會包含必要的設定來建立標記和程式碼後置檔案之間的關聯,如本文所述。

使用此設定後,您可以專注以 XAML 標記定義視窗外觀,並以程式碼後置實作其行為。 下例顯示可定義 Click 事件之事件處理常式按鈕的視窗。 這會在 XAML 中實作,處理常式則會在程式碼後置中實作。

<Window x:Class="WindowsOverview.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WindowsOverview"
        >

    <!-- Client area containing the content of the window -->

    <Button Click="Button_Click">Click This Button</Button>
    
</Window>

下列程式碼是 XAML 的程式碼後置。

using System.Windows;

namespace WindowsOverview
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Button was clicked.");
        }
    }
}
Public Class Window1

    Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
        MessageBox.Show("Button was clicked.")
    End Sub

End Class

設定 MSBuild 的視窗

您實作視窗的方式會決定 MSBuild 視窗的設定方式。 被定義可同時使用 XAML 標記和程式碼後置的視窗:

  • XAML 標記檔案設定為 MSBuild Page 項目。
  • 程式碼後置檔案設定為 MSBuild Compile 項目。

.NET SDK 專案會自動幫您匯入正確的 PageCompile 項目,您不需要宣告這些項目。 針對 WPF 設定專案時,XAML 標記檔案會自動匯入為 Page 項目,而對應的程式碼後置檔案則會匯入為 Compile

MSBuild 專案不會自動匯入類型,您必須自行宣告類型:

<Project>
    ...
    <Page Include="MarkupAndCodeBehindWindow.xaml" />
    <Compile Include=" MarkupAndCodeBehindWindow.xaml.cs" />
    ...
</Project>

如需建置 WPF 應用程式的相關資訊,請參閱編譯 WPF 應用程式

視窗存留期

視窗和所有類別一樣有存留期,會在一開始具現化時開始,之後被開啟、啟動/停用,最終關閉。

開啟視窗

若要開啟視窗,您要先建立其執行個體,如下列範例中示範:

using System.Windows;

namespace WindowsOverview
{
    public partial class App : Application
    {
        private void Application_Startup(object sender, StartupEventArgs e)
        {
            // Create the window
            Window1 window = new Window1();

            // Open the window
            window.Show();
        }
    }
}
Class Application

    Private Sub Application_Startup(sender As Object, e As StartupEventArgs)
        ' Create the window
        Dim window As New Window1

        ' Open the window
        window.Show()
    End Sub

End Class

在此範例中,應用程式啟動時會具現化 Window1,這發生在引發 Startup 事件時。 如需啟動視窗的詳細資訊,請參閱如何取得或設定主要應用程式視窗

當視窗具現化後,其參考即會自動新增至由 Application 物件管理的視窗清單中。 要具現化的第一個視窗會自動由 Application 設定為主要應用程式視窗

視窗最後是經由呼叫 Show 方法所開啟,如下圖所示:

WPF Window with a single button inside.

經由呼叫 Show 所開啟的視窗是「無模式」視窗,而且應用程式不會阻止使用者與應用程式中的其他視窗互動。 以 ShowDialog 開啟視窗會開啟「強制回應」視窗,並限制使用者特定視窗互動。 如需詳細資訊,請參閱對話方塊概觀

呼叫 Show 時,視窗會先執行初始化工作再出現,以建立可接受使用者輸入的基礎結構。 初始化視窗時,會引發 SourceInitialized 事件,並顯示視窗。

如需詳細資訊,請參閱如何開啟視窗或對話方塊

啟動視窗

上例使用 Startup 事件執行顯示初始應用程式視窗的程式碼。 更快捷的方式,是改用 StartupUri 指定應用程式中的 XAML 檔案路徑。 應用程式會自動建立並顯示該屬性所指定的視窗。

<Application x:Class="WindowsOverview.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WindowsOverview"
             StartupUri="ClippedWindow.xaml">
    <Application.Resources>
         
    </Application.Resources>
</Application>

視窗擁有權

使用 Show 方法開啟的視窗,與建立它的視窗沒有隱含關聯性。 使用者可與任一視窗獨立互動,這表示任一視窗皆可執行下列動作:

  • 蓋住其他視窗 (除非其中一個視窗的 Topmost 屬性設定為 true)。
  • 最小化、最大化和還原而不會影響對方。

某些視窗需要與開啟它們的視窗有關聯性。 例如,整合式開發環境 (IDE) 應用程式可能會開啟屬性和工具的視窗,而這些視窗一般會蓋住建立自己的視窗。 此外,這類視窗應該一律與建立它們的視窗一致地關閉、最小化、最大化和還原。 這類關聯性可以藉由讓一個視窗「擁有」另一個視窗而建立,並且藉由使用對「主控視窗」的參考設定「被擁有視窗」Owner 屬性而達成。 下列範例會顯示這一點。

private void Button_Click(object sender, RoutedEventArgs e)
{
    // Create a window and make the current window its owner
    var ownedWindow = new ChildWindow1();
    ownedWindow.Owner = this;
    ownedWindow.Show();
}
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
    ' Create a window and make the current window its owner
    Dim ownedWindow As New ChildWindow1
    ownedWindow.Owner = Me
    ownedWindow.Show()
End Sub

建立擁有權之後︰

  • 被擁有視窗可以透過檢查其 Owner 屬性的值來參考其主控視窗。
  • 主控視窗可以透過檢查其 OwnedWindows 屬性的值來探索它擁有的所有視窗。

視窗啟動

視窗初次開啟後,即會成為使用中視窗。 「使用中視窗」是目前正在擷取使用者輸入的視窗,使用者輸入例如按鍵動作與滑鼠點按。 視窗變為使用中時,它會引發 Activated 事件。

注意

視窗初次開啟後,LoadedContentRendered 事件只會在引發 Activated 事件後被引發。 記住這一點,視窗就可以有效地視為在引發 ContentRendered 時開啟。

視窗成為使用中之後,使用者可以在相同應用程式中啟動另一個視窗,或啟動另一個應用程式。 發生時,目前使用中視窗會失效,並引發 Deactivated 事件。 同樣地,當使用者選取目前失效的視窗時,視窗會再次變成使用中,並引發 Activated

處理 ActivatedDeactivated 的一個常見原因是要啟用與停用只能在使用中視窗內執行的功能。 例如,某些視窗顯示需要使用者持續輸入和注意的互動式內容,包括遊戲和視訊播放程式。 下列範例是簡單的視訊播放程式,會示範如何處理 ActivatedDeactivated 以便實作此行為。

<Window x:Class="WindowsOverview.CustomMediaPlayerWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Activated="Window_Activated"
        Deactivated="Window_Deactivated"
        Title="CustomMediaPlayerWindow" Height="450" Width="800">
    <Grid>
        <MediaElement x:Name="mediaElement" Stretch="Fill"
                      LoadedBehavior="Manual" Source="numbers.mp4" />
    </Grid>
</Window>

下列程式碼是 XAML 的程式碼後置。

using System;
using System.Windows;

namespace WindowsOverview
{
    public partial class CustomMediaPlayerWindow : Window
    {
        public CustomMediaPlayerWindow() =>
            InitializeComponent();

        private void Window_Activated(object sender, EventArgs e)
        {
            // Continue playing media if window is activated
            mediaElement.Play();
        }

        private void Window_Deactivated(object sender, EventArgs e)
        {
            // Pause playing if media is being played and window is deactivated
            mediaElement.Pause();
        }
    }
}
Public Class CustomMediaPlayerWindow
    Private Sub Window_Activated(sender As Object, e As EventArgs)
        ' Continue playing media if window Is activated
        mediaElement.Play()
    End Sub

    Private Sub Window_Deactivated(sender As Object, e As EventArgs)
        ' Pause playing if media is being played and window is deactivated
        mediaElement.Pause()
    End Sub
End Class

當視窗已停用時,其他應用程式類型仍然可能會在背景中執行程式碼。 例如,當使用者使用其他應用程式時,郵件用戶端可能會繼續輪詢郵件伺服器。 這類應用程式在主視窗已停用時,通常會提供不同或額外的行為。 若為郵件程式,這可能表示同時將新的郵件項目加入收件匣,並將通知圖示加入系統匣。 通知圖示需要只在郵件視窗不是使用中時顯示,您可以藉由檢查 IsActive 屬性來判斷郵件視窗是否在使用中。

如果背景工作完成,視窗可能會想要藉由呼叫 Activate 方法,更迫切地通知使用者。 呼叫 Activate 時,如果使用者正在與另一個已啟動的應用程式互動,視窗的工作列按鈕會閃爍。 但若使用者正在與目前的應用程式互動,則呼叫 Activate 會將視窗帶到前景。

注意

您可以使用 Application.ActivatedApplication.Deactivated 事件來處理應用程式範圍的啟動。

避免視窗啟動

在某些案例中,視窗不應該在顯示時啟動,例如聊天應用程式的交談視窗或電子郵件應用程式的通知視窗。

如果您的應用程式具有不應該在顯示時啟動的視窗,您可以先將其 ShowActivated 屬性設定為 false 後,才第一次呼叫 Show 方法。 因此:

  • 視窗未啟動。
  • 不會引發視窗 Activated 的事件。
  • 目前已啟動的視窗會保持已啟動。

不過,當使用者按一下工作區或非工作區來啟動它時,視窗將會啟動。 在此案例中:

  • 視窗已啟動。
  • 會引發視窗 Activated 的事件。
  • 先前已啟動的視窗已停用。
  • 視窗的 DeactivatedActivated 事件會因此而如預期引發,回應使用者動作。

關閉視窗

視窗的存留期在使用者關閉它時開始進入尾聲。 視窗一經關閉,就無法重新開啟。 視窗可以使用非工作區中的項目關閉,包括下列項目︰

  • [系統] 功能表的 [關閉] 項目。
  • 按下 ALT + F4
  • 按下 [關閉] 按鈕。
  • 在強制回應視窗中將 IsCancel 屬性設定為 true 時,按 ESC 鍵。

您可以提供更多機制讓工作區關閉視窗,較常見的包括下列各項:

  • [檔案] 功能表中的 [結束] 項目,通常是針對主要的應用程式視窗。
  • [檔案] 功能表中的 [關閉] 項目,通常是在次要的應用程式視窗。
  • [取消] 按鈕,通常是在強制回應對話方塊。
  • [關閉] 按鈕,通常是在非強制回應對話方塊。

若要關閉視窗以回應其中一種自訂機制,您需要呼叫 Close 方法。 以下範例會實作選擇 [檔案] 功能表的 [結束] 以關閉視窗的功能。

<Window x:Class="WindowsOverview.ClosingWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ClosingWindow" Height="450" Width="800">
    <StackPanel>
        <Menu>
            <MenuItem Header="_File">
                <MenuItem Header="E_xit" Click="fileExitMenuItem_Click" />
            </MenuItem>
        </Menu>
    </StackPanel>
</Window>

下列程式碼是 XAML 的程式碼後置。

using System.Windows;

namespace WindowsOverview
{
    public partial class ClosingWindow : Window
    {
        public ClosingWindow() =>
            InitializeComponent();

        private void fileExitMenuItem_Click(object sender, RoutedEventArgs e)
        {
            // Close the current window
            this.Close();
        }
    }
}
Public Class ClosingWindow
    Private Sub fileExitMenuItem_Click(sender As Object, e As RoutedEventArgs)
        ' Close the current window
        Me.Close()
    End Sub
End Class

注意

應用程式可以設定為在主要應用程式視窗關閉時 (請參閱 MainWindow) 或最後一個視窗關閉時自動關閉。 如需詳細資訊,請參閱ShutdownMode

雖然可以透過非工作區和工作區中提供的機制明確關閉視窗,視窗也可以因為應用程式或 Windows 其他部分的行為而隱含地關閉,包括下列各項:

重要

視窗關閉之後就無法重新開啟。

取消關閉視窗

視窗關閉時會引發兩個事件:ClosingClosed

Closing 會在視窗關閉前引發,其提供的機制可防止關閉視窗。 防止視窗關閉的一個常見原因,是視窗內容包含已修改的資料。 在此情況下,可以處理 Closing 事件,以判斷是否已變更資料,如果是的話,詢問使用者是要繼續關閉視窗而不儲存資料,還是取消關閉視窗。 以下範例示範處理 Closing 的主要層面。

<Window x:Class="WindowsOverview.DataWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="DataWindow" Height="450" Width="800"
        Closing="Window_Closing">
    <Grid>
        <TextBox x:Name="documentTextBox" TextChanged="documentTextBox_TextChanged" />
    </Grid>
</Window>

下列程式碼是 XAML 的程式碼後置。

using System.Windows;
using System.Windows.Controls;

namespace WindowsOverview
{
    public partial class DataWindow : Window
    {
        private bool _isDataDirty;

        public DataWindow() =>
            InitializeComponent();

        private void documentTextBox_TextChanged(object sender, TextChangedEventArgs e) =>
            _isDataDirty = true;

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            // If data is dirty, prompt user and ask for a response
            if (_isDataDirty)
            {
                var result = MessageBox.Show("Document has changed. Close without saving?",
                                             "Question",
                                             MessageBoxButton.YesNo);

                // User doesn't want to close, cancel closure
                if (result == MessageBoxResult.No)
                    e.Cancel = true;
            }
        }
    }
}
Public Class DataWindow

    Private _isDataDirty As Boolean

    Private Sub documentTextBox_TextChanged(sender As Object, e As TextChangedEventArgs)
        _isDataDirty = True
    End Sub

    Private Sub Window_Closing(sender As Object, e As ComponentModel.CancelEventArgs)

        ' If data is dirty, prompt user and ask for a response
        If _isDataDirty Then
            Dim result = MessageBox.Show("Document has changed. Close without saving?",
                                         "Question",
                                         MessageBoxButton.YesNo)

            ' User doesn't want to close, cancel closure
            If result = MessageBoxResult.No Then
                e.Cancel = True
            End If
        End If

    End Sub
End Class

傳遞 Closing 事件處理常式的 CancelEventArgs,會實作可設為 trueCancel 屬性,以防止關閉視窗。

如果未處理 Closing,或是已處理但未取消,則會關閉視窗。 在真正關閉視窗之前,已引發 Closed。 此時無法防止關閉視窗。

視窗存留期事件

下圖顯示在視窗存留期的主體事件順序:

Diagram that shows events in a window's lifetime.

下圖顯示在視窗存留期的主體事件順序,該視窗顯示時沒有啟動 (視窗顯示之前,ShowActivated 已設為 false):

Diagram that shows events in a window's lifetime without activation.

視窗位置

視窗開啟時,它會有相對於桌面的 x 和 y 維度位置。 這個位置可分別調查 LeftTop 屬性而判定。 請設定這些屬性,以變更視窗的位置。

您也可以使用下列 WindowStartupLocation 列舉值之一設定 WindowStartupLocation 屬性,以指定 Window 第一次出現時的初始位置:

如果啟動位置指定為 Manual,但未設定 LeftTop 屬性,則 Window 會向作業系統要求顯示的位置。

最上層視窗和疊置順序

除了有 x 和 y 位置,視窗也有 z 維度的位置,這決定了它相對於其他視窗的垂直位置。 這稱為視窗的疊置順序,並且有兩種類型︰一般疊置順序和最上層疊置順序。 視窗在「一般疊置順序」中的位置取決於它是否目前在使用中。 根據預設,視窗位於一般疊置順序。 視窗在「最上層疊置順序」中的位置也取決於它是否目前在使用中。 此外,最上層疊置順序的視窗一定會位於一般疊置順序的視窗之上。 將視窗的 Topmost 屬性設為 true,即可讓視窗位於最上層疊置順序。

在每個疊置順序類型內,目前使用中視窗會顯示在相同疊置順序中的所有其他視窗之上。

視窗大小

除了有桌面位置,視窗也取決於數個屬性的大小,包括各種寬度和高度屬性和 SizeToContent

MinWidthWidthMaxWidth 是用來管理視窗在存留期內可以擁有的寬度範圍。

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    MinWidth="300" Width="400" MaxWidth="500">
</Window>

視窗高度是由 MinHeightHeightMaxHeight 管理。

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    MinHeight="300" Height="400" MaxHeight="500">
</Window>

因為各種寬度值和高度值都各指定一個範圍,所以可調整大小視窗的高度與寬度可能會是個別維度的指定範圍內的任何位置。 若要偵測其目前的寬度和高度,請分別檢查 ActualWidthActualHeight

如果想將視窗的高度與寬度大小調整成視窗內容的大小,可以使用 SizeToContent 屬性,它具有下列值:

下列範例顯示自動調整垂直和水平大小以符合其內容的視窗,第一次顯示時的樣子。

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    SizeToContent="WidthAndHeight">
</Window>

以下範例示範如何在程式碼中設定 SizeToContent 屬性,以指定如何調整視窗大小使符合其內容。

// Manually alter window height and width
this.SizeToContent = SizeToContent.Manual;

// Automatically resize width relative to content
this.SizeToContent = SizeToContent.Width;

// Automatically resize height relative to content
this.SizeToContent = SizeToContent.Height;

// Automatically resize height and width relative to content
this.SizeToContent = SizeToContent.WidthAndHeight;
' Manually alter window height and width
Me.SizeToContent = SizeToContent.Manual

' Automatically resize width relative to content
Me.SizeToContent = SizeToContent.Width

' Automatically resize height relative to content
Me.SizeToContent = SizeToContent.Height

' Automatically resize height and width relative to content
Me.SizeToContent = SizeToContent.WidthAndHeight

調整大小屬性優先順序

基本上,視窗的各種大小屬性會合併起來定義可調整大小的視窗的寬度和高度範圍。 為了確保維護有效的範圍,Window 會使用下列優先順序來評估調整大小屬性的值。

針對高度屬性:

  1. FrameworkElement.MinHeight
  2. FrameworkElement.MaxHeight
  3. SizeToContent.Height / SizeToContent.WidthAndHeight
  4. FrameworkElement.Height

針對寬度屬性:

  1. FrameworkElement.MinWidth
  2. FrameworkElement.MaxWidth
  3. SizeToContent.Width / SizeToContent.WidthAndHeight
  4. FrameworkElement.Width

優先順序也可以決定視窗最大化時的大小,這由 WindowState 屬性管理。

Window state

在可調整大小的視窗存留期中,它可以有三種狀態︰標準、最小化及最大化。 具有「一般」狀態的視窗是視窗的預設狀態。 這種狀態的視窗如果可以調整大小,使用者就可以移動並使用調整大小底框或框線調整其大小。

如果 ShowInTaskbar 設為 true,則具有「最小化」狀態的視窗可摺疊到其工作列按鈕;否則會摺疊到最小的可能大小,並將自己重新放置到桌面的左下角。 最小化視窗的類型都無法使用框線或調整大小底框來調整大小,雖然未顯示在工作列中的最小化視窗可以在桌面拖曳。

具有「最大化」狀態的視窗會擴展至可達到的最大大小,但只會達到 MaxWidthMaxHeightSizeToContent 屬性指定的大小。 和最小化的視窗一樣,最大化的視窗無法使用調整大小底框或拖曳框線來調整大小。

注意

視窗的 TopLeftWidthHeight 屬性值一律代表正常狀態的值,即使在視窗最大化或最小化的時候。

視窗的狀態可以藉由設定視窗的 WindowState 屬性即可設定視窗狀態,如此可有下列其中一個 WindowState 列舉值:

下列範例示範如何建立在開啟時會顯示為最大化的視窗。

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    WindowState="Maximized">
</Window>

一般情況下,您應該設定 WindowState 以設定視窗的初始狀態。 「可調整大小」的視窗顯示後,使用者可以按下視窗標題列上的最小化、最大化和還原按鈕,以變更視窗狀態。

視窗外觀

您可以新增視窗特定的內容,例如按鈕、標籤和文字方塊,來變更視窗工作區的外觀。 為了設定非工作區,Window 會提供數個屬性,包括設定視窗圖示的 Icon,以及設定其標題的 Title

您也可以藉由設定視窗的調整大小模式、視窗樣式,以及它是否顯示為桌面工作列上的按鈕,變更非工作區框線的外觀和行為。

調整大小模式

WindowStyle 屬性而定,您可以控制使用者是否及如何調整視窗大小。 視窗樣式會影響下列各項:

  • 使用滑鼠拖曳視窗框線以允許或不允許調整大小。
  • 是否在非工作區中顯示 [最小化]、[最大化] 和 [關閉] 按鈕。
  • 是否啟用 [最小化]、[最大化] 和 [關閉] 按鈕。

您可以設定視窗的 ResizeMode 屬性以設定如何調整視窗大小,其可為下列其中一個 ResizeMode 列舉值:

WindowStyle 一樣,您不可能在存留期中變更視窗的調整大小模式,這表示,最可能在 XAML 標記中設定。

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    ResizeMode="CanResizeWithGrip">
</Window>

請注意,您可以藉由檢查 WindowState 屬性來偵測視窗已最大化、最小化,還是還原。

Window style

從視窗非工作區公開的框線適用於大部分的應用程式。 不過,有一些情況下需要不同型別的框線,或是完全不需要框線,視視窗的型別而定。

若要控制視窗得到的框線類型,請使用下列 WindowStyle 列舉值之一設定 WindowStyle 屬性:

下圖顯示套用視窗樣式的效果:

Screenshot that shows how WindowStyle affects a window in WPF.

請注意,上圖不會顯示 SingleBorderWindowThreeDBorderWindow 之間任何明顯的差異。 回到 Windows XP,ThreeDBorderWindow 確實會影響視窗的繪製方式,在工作區中新增了 3D 框線。 從 Windows 7 開始,這兩種樣式之間的差異就非常小。

您可以使用 XAML 標記或程式碼來設定 WindowStyle。 因為不可能在視窗存留期間變更此樣式,所以最可能使用 XAML 標記設定。

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    WindowStyle="ToolWindow">
</Window>

非矩形視窗樣式

有時候,WindowStyle 允許的框線樣式不足。 例如,您可能想要建立非矩形框線的應用程式,像 Microsoft Windows Media Player 使用的那樣。

例如,考慮使用下圖中的語音泡泡視窗:

Screenshot of a WPF window that has a clipped area and custom shape.

WindowStyle 屬性設定為 None,以及使用 Window 對透明度的特殊支援,可建立這類型的視窗。

<Window x:Class="WindowsOverview.ClippedWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ClippedWindow" SizeToContent="WidthAndHeight"
        WindowStyle="None" AllowsTransparency="True" Background="Transparent">
    <Grid Margin="20">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="20"/>
        </Grid.RowDefinitions>

        <Rectangle Stroke="#FF000000" RadiusX="10" RadiusY="10"/>
        <Path Fill="White" Stretch="Fill" Stroke="#FF000000" HorizontalAlignment="Left" Margin="15,-5.597,0,-0.003" Width="30" Grid.Row="1" Data="M22.166642,154.45381 L29.999666,187.66699 40.791059,154.54395"/>
        <Rectangle Fill="White" RadiusX="10" RadiusY="10" Margin="1"/>
        
        <TextBlock HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="25" Text="Greetings!" TextWrapping="Wrap" Margin="5,5,50,5"/>
        <Button HorizontalAlignment="Right" VerticalAlignment="Top" Background="Transparent" BorderBrush="{x:Null}" Foreground="Red" Content="❌" FontSize="15" />

        <Grid.Effect>
            <DropShadowEffect BlurRadius="10" ShadowDepth="3" Color="LightBlue"/>
        </Grid.Effect>
    </Grid>
</Window>

這些值的組合會指示視窗要轉譯成透明。 在此狀態中,無法使用視窗的非工作區裝飾按鈕,而您必須提供自己的按鈕。

工作列目前狀態

視窗的預設外觀包含工作列按鈕。 有些類型的視窗沒有工作列按鈕,例如訊息方塊、對話方塊,或 WindowStyle 屬性設為 ToolWindow 的視窗。 您可以藉由設定 ShowInTaskbar 屬性 (預設為 true) 以控制是否顯示視窗的工作列按鈕。

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    ShowInTaskbar="False">
</Window>

其他類型的視窗

NavigationWindow 是設計裝載可瀏覽內容的視窗。

對話方塊是經常用來從使用者收集資訊以完成一項功能的視窗。 例如,當使用者想要開啟檔案時,應用程式會顯示 [開啟檔案] 對話方塊,以從使用者取得檔案名稱。 如需詳細資訊,請參閱對話方塊概觀

另請參閱