WPF 창 개요(WPF .NET)

사용자는 WPF(Windows Presentation Foundation) 애플리케이션을 창을 통해 조작합니다. 창의 기본 용도는 데이터를 시각화하는 콘텐츠를 호스트하고 사용자가 데이터와 상호 작용할 수 있도록 하는 것입니다. WPF 애플리케이션은 Window 클래스를 사용하여 자체 창을 제공합니다. 이 문서에서는 Window를 소개한 다음, 애플리케이션에서 창을 만들고 관리하는 방법의 기본 사항을 다룹니다.

중요

여기서는 C# 프로젝트에서 생성된 XAML을 사용합니다. Visual Basic을 사용하는 경우에는 XAML이 약간 다를 수 있습니다. 해당 차이점은 일반적으로 x:Class 특성 값에 나타납니다. C#에는 프로젝트의 루트 네임스페이스가 포함되지만 Visual Basic은 그러지 않습니다.

C#의 프로젝트 템플릿은 app.xaml 파일에 포함된 App 형식을 만듭니다. Visual Basic에서는 형식 이름은 Application이고 파일 이름은 Application.xaml입니다.

Window 클래스

WPF에서 창은 다음을 수행하기 위해 사용하는 Window 클래스에 의해 캡슐화됩니다.

  • 창을 표시합니다.
  • 창의 크기, 위치 및 모양을 구성합니다.
  • 애플리케이션별 콘텐츠를 호스팅합니다.
  • 창의 수명을 관리합니다.

다음 그림에서는 창을 구성하는 부분을 보여 줍니다.

WPF 창의 부분을 보여 주는 스크린샷

창은 비클라이언트 영역과 클라이언트 영역의 두 영역으로 나뉩니다.

창의 ‘비클라이언트 영역’은 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)은 Window에서 파생되는 partial 클래스를 x:Class 특성에 지정하는 이름으로 생성합니다. 이를 위해서는 XAML 스키마(xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml")의 XML 네임스페이스 선언을 추가해야 합니다. 생성된 partial 클래스는 InitializeComponent 메서드를 구현하고, 이 메서드는 이벤트를 등록하고 태그에서 구현되는 속성을 설정하기 위해 호출됩니다.

  • 코드 숨김에서 클래스는 태그의 x:Class 특성으로 지정된 이름과 같은 이름을 가진 partial 클래스여야 하며 Window에서 파생되어야 합니다. 이를 통해 애플리케이션 빌드 시 태그 파일에 대해 생성되는 partial 클래스와 코드 숨김 파일을 연결할 수 있습니다. 자세한 내용은 WPF 애플리케이션 컴파일을 참조하세요.

  • 코드 숨김에서 Window 클래스는 InitializeComponent 메서드를 호출하는 생성자를 구현해야 합니다. InitializeComponent는 태그 파일에서 생성된 partial 클래스에 의해 구현되어 이벤트를 등록하고 태그에 정의된 속성을 설정합니다.

참고

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 이벤트가 발생할 때 인스턴스화됩니다. 시작 창에 대한 자세한 내용은 How to get or set the main application window(주 애플리케이션 창을 가져오거나 설정하는 방법)를 참조하세요.

창이 인스턴스화되면 창에 대한 참조가 Application 개체에서 관리되는 창 목록에 자동으로 추가됩니다. 처음 인스턴스화하는 창은 자동으로 Application에서 주 애플리케이션 창으로 설정합니다.

최종적으로 Show 메서드를 호출하여 다음 이미지와 같이 창이 열립니다.

안에 단추 하나가 있는 WPF 창

Show를 호출하여 열리는 창은 ‘모덜리스’ 창이며 사용자가 애플리케이션의 다른 창을 조작하지 못하게 되지 않습니다. ShowDialog를 사용하여 창을 열면 창이 ‘모달’로 열리며 사용자가 해당 특정 창만 조작할 수 있습니다. 자세한 내용은 대화 상자 개요를 참조하세요.

Show를 호출하면 창은 초기화 작업을 수행한 후 표시되어 사용자 입력을 받을 수 있는 인프라를 설정합니다. 창이 초기화되면 SourceInitialized 이벤트가 발생하고 창이 표시됩니다.

자세한 내용은 How to open a window or dialog box(창 또는 대화 상자를 여는 방법)를 참조하세요.

시작 창

이전 예제에서는 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 이벤트를 사용하여 처리할 수 있습니다.

창 활성화 방지

채팅 애플리케이션의 대화 창이나 전자 메일 애플리케이션의 알림 창과 같이 창이 표시될 때 활성화하지 않아야 하는 경우가 있습니다.

애플리케이션에 표시될 때 활성화하지 않아야 할 창이 있는 경우에는 Show 메서드를 처음으로 호출하기 전에 해당 창의 ShowActivated 속성을 false로 설정할 수 있습니다. 이렇게 하면 다음과 같은 결과가 나타납니다.

  • 창이 활성화되지 않습니다.
  • 창의 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는 창이 닫히지 않도록 하기 위해 true로 설정한 Cancel 속성을 구현합니다.

Closing이 처리되지 않거나 처리되지만 취소되지 않으면 창이 닫힙니다. 창이 실제로 닫히기 직전에 Closed가 발생합니다. 이 시점에서는 창 닫기를 방지할 수 없습니다.

창 수명 이벤트

다음 그림에서는 창의 수명에서 발생하는 주요 이벤트를 순서대로 보여 줍니다.

창의 수명에서 발생하는 이벤트를 보여 주는 다이어그램

다음 그림에서는 활성화되지 않고 표시되는 창(창을 표시하기 전에 ShowActivatedfalse로 설정됨)의 수명 동안 발생하는 주요 이벤트를 순서대로 보여 줍니다.

활성화되지 않는 창의 수명 동안 발생하는 이벤트를 보여 주는 다이어그램

창 위치

창은 열릴 때 바탕 화면에 상대적인 x 및 y 크기의 위치를 가집니다. 이 위치는 각각 LeftTop 속성을 검사하여 확인할 수 있습니다. 이 속성을 설정하여 창의 위치를 변경할 수 있습니다.

또한 Window의 초기 위치도 지정할 수 있는데, 처음 표시될 때 WindowStartupLocation 속성을 다음 WindowStartupLocation 열거형 값 중 하나로 설정하면 됩니다.

시작 위치를 Manual로 지정하고 LeftTop 속성을 설정하지 않은 경우 Window에서는 표시될 위치를 운영 체제에 묻습니다.

최상위 창 및 z 순서

창에는 x 및 y 위치 이외에도 다른 창과 상대적인 수직 위치를 결정하는 z 차원의 위치도 있습니다. 이를 창의 z 순서라고 하며 여기에는 일반 z 순서와 최상위 z 순서의 두 가지 유형이 있습니다. ‘일반 z 순서’에서 창의 위치는 현재 활성화되었는지 여부에 따라 결정됩니다. 기본적으로 창은 일반 z 순서로 배치됩니다. ‘최상위 z 순서’에서 창의 위치도 현재 활성화되었는지 여부에 따라 결정됩니다. 최상위 z 수준의 창은 항상 일반 z 순서 창의 위에 위치합니다. 창의 Topmost 속성을 true로 설정하면 창이 최상위 z 순서로 배치됩니다.

각 z 순서 유형 안에서는 현재 활성화된 창이 같은 z 순서의 다른 모든 창 위에 나타납니다.

창 크기

창은 바탕 화면 위치 이외에도 다양한 너비 및 높이 속성과 SizeToContent를 비롯한 몇 가지 속성에 의해 결정되는 크기를 가집니다.

MinWidth, Width, MaxWidth 속성을 사용하면 창이 수명 동안 가질 수 있는 너비의 범위를 관리할 수 있습니다.

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

창 높이는 MinHeight, Height, MaxHeight로 관리합니다.

<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 속성으로 관리되는 최대화되었을 때의 창 크기도 결정됩니다.

창 상태

크기 조정 가능한 창의 수명은 표준, 최소화 및 최대화의 세 가지 상태를 가질 수 있습니다. ‘표준’ 상태는 창의 기본 상태입니다. 크기 조정 가능 창이 표준 상태인 경우 사용자는 크기 조정 그립이나 테두리를 사용하여 창을 이동하고 크기 조정할 수 있습니다.

‘최소화’ 상태의 창은 ShowInTaskbartrue로 설정된 경우 작업 표시줄 단추로 축소됩니다. 그러지 않은 경우에는 가능한 가장 작은 크기로 축소되고 바탕 화면의 왼쪽 아래 모서리로 저절로 이동됩니다. 이러한 최소화된 창 유형은 테두리나 크기 조정 그립을 사용하여 크기 조정할 수 없습니다. 하지만 작업 표시줄에 표시되지 않은 최소화된 창은 바탕 화면에서 끌 수 있습니다.

‘최대화’ 상태의 창은 가능한 최대 크기로 확장되며 MaxWidth, MaxHeight, SizeToContent 속성에 지정된 크기까지 확대될 수 있습니다. 최소화된 창과 마찬가지로 최대화된 창은 크기 조정 그립을 사용하거나 테두리를 끌어서 크기 조정할 수 없습니다.

참고

창의 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 속성을 검사하여 창의 최대화, 최소화, 복원 여부를 감지할 수 있습니다.

창 스타일

창의 비클라이언트 영역에서 노출되는 테두리는 대부분의 애플리케이션에 적합합니다. 하지만 창의 유형에 따라 다른 유형의 테두리가 필요하거나 테두리가 전혀 필요 없는 경우가 있습니다.

창의 테두리 유형을 제어하려면 WindowStyle 속성을 다음과 같은 WindowStyle 열거형 값 중 하나로 설정합니다.

창 스타일을 적용한 효과는 다음 이미지와 나와 있습니다.

WindowStyle이 WPF의 창에 미치는 영향을 보여 주는 스크린샷

위 이미지에서는 SingleBorderWindowThreeDBorderWindow 간에 뚜렷한 차이가 보이지 않습니다. 이전의 Windows XP에서는 ThreeDBorderWindow가 창이 표시되는 방식에 영향을 미쳐 클라이언트 영역에 3D 테두리를 추가했습니다. Windows 7부터 두 스타일의 차이는 아주 적습니다.

WindowStyle은 XAML 태그나 코드를 사용하여 설정할 수 있습니다. 창의 수명 동안 변경될 가능성이 적으므로 대부분 XAML 태그를 사용하여 구성합니다.

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

사각형이 아닌 창 스타일

WindowStyle로 사용할 수 있는 테두리 스타일만으로는 부족한 경우가 있을 수 있습니다. 예를 들어 Microsoft Windows Media Player에서처럼 사각형이 아닌 테두리가 사용된 애플리케이션을 만들고자 할 수 있습니다.

예를 들어 다음 이미지와 같은 말 상자 창을 고려해 보겠습니다.

잘린 영역이 있는 사용자 지정 모양의 WPF 창을 보여 주는 스크린샷

해당 유형의 창은 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는 탐색 가능한 콘텐츠를 호스트하기 위한 창입니다.

대화 상자는 기능 수행을 위해 사용자로부터 정보를 수집할 때 많이 사용됩니다. 예를 들어 사용자가 파일을 열려고 할 때는 사용자에게 파일 이름을 얻기 위해 애플리케이션은 일반적으로 파일 열기 대화 상자를 엽니다. 자세한 내용은 대화 상자 개요를 참조하세요.

참고 항목