자습서: .NET을 사용하여 새 WPF 앱 만들기
이 자습서에서는 Visual Studio를 사용하여 새 WPF(Windows Presentation Foundation) 앱을 만드는 방법을 알아봅니다. Visual Studio를 사용하면 창에 컨트롤을 추가하여 앱의 UI를 디자인하고 해당 컨트롤의 입력 이벤트를 처리하여 사용자와 상호 작용합니다. 이 자습서를 마치면 목록 상자에 이름을 추가하는 간단한 앱이 있습니다.
이 자습서에서는 다음을 수행합니다.
- 새 WPF 앱을 만듭니다.
- 창에 컨트롤을 추가합니다.
- 컨트롤 이벤트를 처리하여 앱 기능을 제공합니다.
- 앱을 실행합니다.
이 자습서를 수행하는 동안 만든 앱의 미리 보기는 다음과 같습니다.
필수 조건
주의
.NET 6은 더 이상 지원되지 않습니다. .NET 9.0을 사용하는 것이 좋습니다.
- Visual Studio 2022 버전 17.0 이상
- .NET 데스크톱 개발 워크로드를 선택합니다.
- .NET 6 개별 구성 요소를 선택합니다.
주의
.NET 7은 더 이상 지원되지 않습니다. .NET 9.0을 사용하는 것이 좋습니다.
- Visual Studio 2022 버전 17.4 이상
- .NET 데스크톱 개발 워크로드를 선택합니다.
- .NET 7 개별 구성 요소를 선택합니다
WPF 앱 만들기
새 앱을 만드는 첫 번째 단계는 Visual Studio를 열고 템플릿을 통해 앱을 생성하는 것입니다.
Visual Studio를 엽니다.
새 프로젝트 만들기를 선택합니다.
템플릿 검색 상자에 wpf를 입력하고 Enter 키를 누릅니다.
코드 언어 드롭다운에서 C# 또는 Visual Basic을 선택합니다.
템플릿 목록에서 WPF 애플리케이션을 선택하고 다음을 선택합니다.
중요
WPF 애플리케이션(.NET Framework) 템플릿을 선택하지 마세요.
다음 이미지는 C# 및 Visual Basic .NET 프로젝트 템플릿을 모두 보여 줍니다. 코드 언어 필터를 적용한 경우 해당 언어에 대한 템플릿만 표시됩니다.
새 프로젝트 구성 창에서 다음을 수행합니다.
- 프로젝트 이름 상자에 Names를 입력합니다.
- 동일한 디렉터리에 솔루션과 프로젝트 배치 확인란을 선택합니다.
- 필요에 따라 다른 위치를 선택하여 코드를 저장합니다.
- 다음 단추를 선택합니다.
추가 정보 창에서 대상 프레임워크에 대해 .NET 6.0(장기 지원)을 선택합니다. 생성 단추를 선택합니다.
Visual Studio를 엽니다.
새 프로젝트 만들기를 선택합니다.
템플릿 검색 상자에 wpf를 입력하고 Enter 키를 누릅니다.
코드 언어 드롭다운에서 C# 또는 Visual Basic을 선택합니다.
템플릿 목록에서 WPF 애플리케이션을 선택하고 다음을 선택합니다.
중요
WPF 애플리케이션(.NET Framework) 템플릿을 선택하지 마세요.
다음 이미지는 C# 및 Visual Basic .NET 프로젝트 템플릿을 모두 보여 줍니다. 코드 언어 필터를 적용한 경우 해당 언어에 대한 템플릿만 표시됩니다.
새 프로젝트 구성 창에서 다음을 수행합니다.
- 프로젝트 이름 상자에 Names를 입력합니다.
- 동일한 디렉터리에 솔루션과 프로젝트 배치 확인란을 선택합니다.
- 필요에 따라 다른 위치를 선택하여 코드를 저장합니다.
- 다음 단추를 선택합니다.
추가 정보 창에서 대상 프레임워크에 대해 .NET 7.0(표준 기간 지원)을 선택합니다. 생성 단추를 선택합니다.
Visual Studio를 엽니다.
새 프로젝트 만들기를 선택합니다.
템플릿 검색 상자에 wpf를 입력하고 Enter 키를 누릅니다.
코드 언어 드롭다운에서 C# 또는 Visual Basic을 선택합니다.
템플릿 목록에서 WPF 애플리케이션을 선택하고 다음을 선택합니다.
중요
WPF 애플리케이션(.NET Framework) 템플릿을 선택하지 마세요.
다음 이미지는 C# 및 Visual Basic .NET 프로젝트 템플릿을 모두 보여 줍니다. 코드 언어 필터를 적용한 경우 해당 언어에 대한 템플릿만 표시됩니다.
새 프로젝트 구성 창에서 다음을 수행합니다.
- 프로젝트 이름 상자에 Names를 입력합니다.
- 동일한 디렉터리에 솔루션과 프로젝트 배치 확인란을 선택합니다.
- 필요에 따라 다른 위치를 선택하여 코드를 저장합니다.
- 다음 단추를 선택합니다.
추가 정보 창에서 대상 프레임워크에 대한 .NET 8.0(장기 지원)을 선택합니다. 생성 단추를 선택합니다.
Visual Studio를 엽니다.
새 프로젝트 만들기를 선택합니다.
템플릿 검색 상자에 wpf를 입력하고 Enter 키를 누릅니다.
코드 언어 드롭다운에서 C# 또는 Visual Basic을 선택합니다.
템플릿 목록에서 WPF 애플리케이션을 선택하고 다음을 선택합니다.
중요
WPF 애플리케이션(.NET Framework) 템플릿을 선택하지 마세요.
다음 이미지는 C# 및 Visual Basic .NET 프로젝트 템플릿을 모두 보여 줍니다. 코드 언어 필터를 적용한 경우 해당 언어에 대한 템플릿만 표시됩니다.
새 프로젝트 구성 창에서 다음을 수행합니다.
- 프로젝트 이름 상자에 Names를 입력합니다.
- 동일한 디렉터리에 솔루션과 프로젝트 배치 확인란을 선택합니다.
- 필요에 따라 다른 위치를 선택하여 코드를 저장합니다.
- 다음 단추를 선택합니다.
추가 정보 창에서 대상 프레임워크에 대한 .NET 9.0(표준 용어 지원)을 선택합니다. 생성 단추를 선택합니다.
앱이 생성되면 Visual Studio에서 기본 창 인 MainWindow에 대한 XAML 디자이너 창을 열어야 합니다. 디자이너가 표시되지 않으면 솔루션 탐색기 창에서 MainWindow.xaml 파일을 두 번 클릭하여 디자이너를 엽니다.
Visual Studio의 중요 부분
Visual Studio에서 WPF에 대한 지원에는 앱을 만들 때 상호 작용하는 5가지 중요한 구성 요소가 있습니다.
솔루션 탐색기
모든 프로젝트 파일, 코드, 창, 리소스가 이 창에 표시됩니다.
속성
이 창에는 선택한 항목에 따라 구성할 수 있는 속성 설정이 표시됩니다. 예를 들어 솔루션 탐색기에서 항목을 선택하면 해당 파일과 관련된 속성 설정이 표시됩니다. 디자이너에서 개체를 선택하면 요소에 대한 설정이 표시됩니다. 이전 이미지와 관련하여 디자이너에서 창의 제목 표시줄이 선택되었습니다.
도구 상자
도구 상자에는 디자인 화면에 추가할 수 있는 모든 컨트롤이 포함되어 있습니다. 현재 화면에 컨트롤을 추가하려면 컨트롤을 두 번 클릭하거나 컨트롤을 화면에 끌어서 놓습니다. XAML 디자이너 창을 사용하여 결과를 미리 보는 동안 XAML 코드 편집기 창을 사용하여 UI(사용자 인터페이스)를 디자인하는 것이 일반적입니다.
XAML 디자이너
XAML 문서용 디자이너입니다. 대화형으로 작동하며, 도구 상자에서 개체를 끌어다 놓을 수 있습니다. 디자이너에서 항목을 선택하고 이동하여 앱에 대한 UI를 시각적으로 작성할 수 있습니다.
디자이너와 편집기가 모두 표시되는 경우 하나에 대한 변경 내용이 다른 것에도 반영됩니다.
디자이너 에서 항목을 선택하면 속성 창에 해당 개체에 대한 속성과 특성이 표시됩니다.
XAML 코드 편집기
XAML 문서용 XAML 코드 편집기입니다. XAML 코드 편집기는 디자이너 없이 UI를 수동으로 작성하는 방법입니다. 디자이너는 컨트롤이 디자이너에 추가될 때 컨트롤의 속성을 자동으로 설정할 수 있습니다. XAML 코드 편집기는 더 많은 제어 기능을 제공합니다.
디자이너와 편집기가 모두 표시되는 경우 하나에 대한 변경 내용이 다른 것에도 반영됩니다. 코드 편집 기에서 텍스트 캐리트를 탐색할 때 속성 창에는 해당 개체에 대한 속성과 특성이 표시됩니다.
XAML 검사
프로젝트를 만든 후에는 창을 표시하기 위한 최소한의 XAML 코드로 XAML 코드 편집기가 표시됩니다. 편집기가 열려 있지 않으면 솔루션 탐색기 창에서 MainWindow.xaml 항목을 두 번 클릭합니다. 다음 예제와 유사한 XAML이 표시됩니다.
<Window x:Class="Names.MainWindow"
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:Names"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
</Grid>
</Window>
Important
Visual Basic에서 코딩하는 경우 XAML은 특성과 x:Class=".."
약간 다릅니다. Visual Basic의 XAML은 개체의 클래스 이름을 사용하고 네임스페이스를 클래스로 생략합니다.
XAML을 더 잘 이해하기 위해 XAML을 세분화해 보겠습니다. XAML은 WPF에서 UI를 만들기 위해 처리하는 단순한 XML입니다. XAML을 이해하려면 최소한 XML의 기본 사항을 숙지해야 합니다.
문서 루트 <Window>
는 XAML 파일에서 설명하는 개체의 형식을 나타냅니다. 선언된 특성이 8개이며 이들은 일반적으로 세 개의 범주에 속합니다.
XML 네임스페이스
XML 네임스페이스는 XML에 대한 구조체를 제공하여 파일에서 선언할 수 있는 XML 콘텐츠를 결정합니다.
기본
xmlns
특성은 전체 파일에 대한 XML 네임스페이스를 가져오며 이 경우에는 WPF에 의해 선언된 형식에 매핑됩니다. 다른 XML 네임스페이스는 접두사를 선언하고 XAML 파일에 대한 다른 형식 및 개체를 가져옵니다. 예를 들어xmlns:local
네임스페이스는local
접두사를 선언하고 프로젝트에 의해 선언된 개체,Names
코드 네임스페이스에서 선언된 개체에 매핑됩니다.x:Class
특성이 특성은 코드에서 정의한 형식인 MainWindow.xaml.cs 또는 MainWindow.xaml.vb 파일(C# 및
MainWindow
Visual Basic의Names.MainWindow
클래스)에 매핑<Window>
됩니다.Title
특성XAML 개체에 선언된 모든 일반 특성은 해당 개체의 속성을 설정합니다. 이 경우
Title
특성은Window.Title
속성을 설정합니다.
창 변경
예제 앱의 경우 이 창이 너무 크며 제목 표시줄이 설명을 제공하지 않습니다. 이 문제를 해결해 보겠습니다.
먼저 F5 키를 누르거나 메뉴에서 디버그>시작 디버깅을 선택하여 앱을 실행합니다.
컨트롤 없이 템플릿에서 생성된 기본 창과 MainWindow의 제목이 표시됩니다.
를 설정하여 창의 제목을 변경합니다
Title
Names
.를 설정
Width
180
하여 창의 크기를 변경합니다Height
260
.<Window x:Class="Names.MainWindow" 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:Names" mc:Ignorable="d" Title="Names" Height="180" Width="260"> <Grid> </Grid> </Window>
레이아웃 준비
WPF는 다양한 레이아웃 컨트롤을 갖춘 강력한 레이아웃 시스템을 제공합니다. 레이아웃 컨트롤은 자식 컨트롤을 배치하고 크기를 조정하는 데 도움이 되며 이를 자동으로 수행할 수도 있습니다. 이 XAML에서 사용자에게 제공되는 기본 레이아웃 컨트롤은 <Grid>
컨트롤입니다.
표 컨트롤을 사용하면 테이블과 마찬가지로 행과 열을 정의하고 특정 행과 열 조합의 범위 내에 컨트롤을 배치할 수 있습니다. 여러 자식 컨트롤 또는 다른 레이아웃 컨트롤을 그리드에 추가할 수 있습니다. 예를 들어 특정 행과 열 조합에 다른 <Grid>
컨트롤을 배치할 수 있으며 새 그리드는 더 많은 행과 열을 정의하고 고유한 자식을 가질 수 있습니다.
그리드 컨트롤은 자식 컨트롤을 행과 열에 배치합니다. 그리드에는 항상 단일 행과 열이 선언되어 있습니다. 즉, 기본적으로 그리드는 단일 셀입니다. 이 상태에서는 컨트롤을 유연하게 배치할 수 없습니다.
이 앱에 필요한 컨트롤의 그리드 레이아웃을 조정합니다.
요소에 새 특성을
<Grid>
추가합니다Margin="10"
.이 설정은 창 가장자리에서 그리드를 가져오고 좀 더 멋지게 보이게 합니다.
두 개의 행과 두 개의 열을 정의하여 그리드를 4개의 셀로 나눠 줍니다.
<Grid Margin="10"> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> </Grid>
XAML 코드 편집기 또는 XAML 디자이너에서 그리드를 선택하면 XAML 디자이너에 각 행과 열이 표시되는 것을 확인할 수 있습니다.
첫 번째 컨트롤 추가
이제 그리드가 구성되었으므로 컨트롤 추가를 시작할 수 있습니다. 먼저 레이블 컨트롤로 시작합니다.
행 및 열 정의 뒤의
<Grid>
요소 내에 새<Label>
요소를 만듭니다. 요소의 내용을 다음 문자열 값Names
으로 설정합니다.<Grid Margin="10"> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Label>Names</Label> </Grid>
<Label>Names</Label>
는Names
콘텐츠를 정의합니다. 일부 컨트롤은 콘텐츠를 처리하는 방법을 이해하고 나머지는 이해하지 못합니다. 컨트롤의 콘텐츠는Content
속성에 매핑됩니다. XAML 특성 구문을 통해 콘텐츠를 설정할 때<Label Content="Names" />
형식을 사용하게 됩니다. 두 가지 방법 모두Names
텍스트를 표시하도록 레이블의 콘텐츠를 설정하여 동일한 작업을 수행합니다.레이블은 표의 첫 번째 행과 열에 자동으로 배치되므로 창의 절반을 차지합니다. 첫 번째 행의 경우 레이블에 해당 행만 사용할 것이므로 많은 공간이 필요하지 않습니다.
첫 번째
<RowDefinition>
의Height
특성을*
에서Auto
로 변경합니다.Auto
값은 그리드 행의 크기를 콘텐츠(이 경우 레이블 컨트롤)의 크기로 자동으로 조정합니다.<Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions>
이제 디자이너에는 사용 가능한 높이의 작은 공간을 차지하는 레이블이 표시됩니다. 이제 다음 행이 차지할 공간이 더 마련되었습니다.
컨트롤 배치
컨트롤 배치에 대해 알아보겠습니다. 이전 섹션에서 만든 레이블은 표의 행 0과 열 0에 자동으로 배치되었습니다. 행 및 열에 대한 번호 매기기 시작 0에서 1씩 증가 합니다. 컨트롤은 그리드에 대해 아무것도 모르며 그리드 내의 배치를 제어하는 어떤 속성도 정의하지 않습니다.
컨트롤이 그리드를 알지 못하는데 어떻게 다른 행이나 열을 사용하도록 컨트롤에 지시합니까? 연결된 속성을 통해 가능합니다. 그리드는 WPF에서 제공하는 강력한 속성 시스템을 활용합니다.
그리드 컨트롤은 자식 컨트롤이 자신에게 연결할 수 있는 새 속성을 정의합니다. 속성은 실제로 컨트롤 자체에 존재하지 않으며 그리드에 추가되면 컨트롤에서 사용할 수 있습니다.
그리드는 자식 컨트롤의 행과 열 배치를 결정하는 두 가지 속성인 Grid.Row
및 Grid.Column
을 정의합니다. 이러한 속성이 컨트롤에서 생략되면 기본값이 0임을 의미하므로 컨트롤은 그리드의 0
행과 0
열에 배치됩니다. Grid.Column
특성을 1
로 설정하여 <Label>
컨트롤의 배치를 변경해 봅니다.
<Label Grid.Column="1">Names</Label>
레이블이 두 번째 열로 이동되었습니다. 다음에 만들 컨트롤을 배치하기 위해 연결된 속성 Grid.Row
및 Grid.Column
을 사용할 수 있습니다. 하지만 지금은 레이블을 열 0으로 복원합니다.
이름 목록 상자 만들기
이제 그리드 크기가 올바르게 조정되고 레이블이 만들어졌으므로 레이블 아래 행에 목록 상자 컨트롤을 추가합니다.
<ListBox />
컨트롤 아래에 컨트롤을 선언합니다<Label>
.Grid.Row
속성을1
로 설정합니다.x:Name
속성을lstNames
로 설정합니다.컨트롤의 이름이 지정되면 코드 숨김에서 참조할 수 있습니다. 이름은
x:Name
특성과 함께 컨트롤에 할당됩니다.
XAML의 모양은 다음과 같습니다.
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label>Names</Label>
<ListBox Grid.Row="1" x:Name="lstNames" />
</Grid>
나머지 컨트롤 추가
추가할 마지막 두 컨트롤은 사용자가 목록 상자에 추가할 이름을 입력하는 데 사용하는 텍스트 상자와 단추입니다. 그러나 이러한 컨트롤을 정렬하기 위해 그리드에 더 많은 행과 열을 만드는 대신 이러한 컨트롤을 레이아웃 컨트롤에 <StackPanel>
배치합니다.
스택 패널은 컨트롤이 배치되는 방법에서 그리드와 다릅니다. 컨트롤이 연결된 속성과 Grid.Column
함께 Grid.Row
사용할 위치를 그리드에 알려주는 동안 스택 패널은 자동으로 각 자식 컨트롤을 순차적으로 배치합니다. 각 컨트롤을 서로 "스택"합니다.
<StackPanel>
컨트롤 아래에 컨트롤을 선언합니다<ListBox>
.Grid.Row
속성을1
로 설정합니다.Grid.Column
속성을1
로 설정합니다.Margin
를5,0,0,0
로 설정합니다.<Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Label>Names</Label> <ListBox Grid.Row="1" x:Name="lstNames" /> <StackPanel Grid.Row="1" Grid.Column="1" Margin="5,0,0,0"> </StackPanel>
Margin
특성은 이전에 그리드에서 사용되었지만 단일 값10
만 입력했습니다. 이 여백의 값5,0,0,0
은10
. margin 속성은 형식이며Thickness
두 값을 모두 해석할 수 있습니다. 두께는 직사각형 프레임에서 각 측면 주변의 공간, 즉 왼쪽, 위쪽, 오른쪽, 아래쪽을 각각 정의합니다. 여백 값이 단일 값이면 네 개의 면에 모두 해당 값이 사용됩니다.컨트롤 내부에
<StackPanel>
컨트롤을 만듭니다<TextBox />
.x:Name
속성을txtName
로 설정합니다.
마지막으로, 컨트롤의
<TextBox>
내부에<StackPanel>
있는 후 컨트롤을 만듭니다<Button>
.x:Name
속성을btnAdd
로 설정합니다.Margin
를0,5,0,0
로 설정합니다.- 콘텐츠를
Add Name
.로 설정합니다.
XAML의 모양은 다음과 같습니다.
<StackPanel Grid.Row="1" Grid.Column="1" Margin="5,0,0,0">
<TextBox x:Name="txtName" />
<Button x:Name="btnAdd" Margin="0,5,0,0">Add Name</Button>
</StackPanel>
창에 대한 레이아웃이 완료되었습니다. 그러나 앱에는 실제로 작동하기 위한 논리가 없습니다. 이제 컨트롤 이벤트를 코드에 연결하고 앱이 실제로 작업을 수행하도록 해야 합니다.
Click 이벤트에 대한 코드 추가
우리가 만든 <Button>
에는 사용자가 단추를 누를 때 발생하는 Click
이벤트가 있습니다. 이 이벤트를 구독하고 목록 상자에 이름을 추가하는 코드를 추가할 수 있습니다. XAML 특성은 속성을 설정하는 데 사용되는 것처럼 이벤트를 구독하는 데 사용됩니다.
컨트롤을 찾습니다
<Button>
.Click
특성을ButtonAddName_Click
으로 설정합니다.<StackPanel Grid.Row="1" Grid.Column="1" Margin="5,0,0,0"> <TextBox x:Name="txtName" /> <Button x:Name="btnAdd" Margin="0,5,0,0" Click="ButtonAddName_Click">Add Name</Button> </StackPanel>
이벤트 처리기 코드를 생성합니다.
ButtonAddName_Click
을 마우스 오른쪽 단추로 클릭하고 정의로 이동을 선택합니다.이 작업은 제공된 처리기 이름과 일치하는 메서드를 코드 숨김에 생성합니다.
private void ButtonAddName_Click(object sender, RoutedEventArgs e) { }
Private Sub ButtonAddName_Click(sender As Object, e As RoutedEventArgs) End Sub
이제 세 단계를 수행하여 다음 코드를 추가합니다.
- 텍스트 상자에 이름이 포함되어 있는지 확인합니다.
- 텍스트 상자에 입력한 이름이 아직 존재하지 않는지 확인합니다.
- 목록 상자에 이름을 추가합니다.
private void ButtonAddName_Click(object sender, RoutedEventArgs e) { if (!string.IsNullOrWhiteSpace(txtName.Text) && !lstNames.Items.Contains(txtName.Text)) { lstNames.Items.Add(txtName.Text); txtName.Clear(); } }
Private Sub ButtonAddName_Click(sender As Object, e As RoutedEventArgs) If Not String.IsNullOrWhiteSpace(txtName.Text) And Not lstNames.Items.Contains(txtName.Text) Then lstNames.Items.Add(txtName.Text) txtName.Clear() End If End Sub
앱 실행
이제 이벤트가 처리되었으므로 앱을 실행합니다. 창이 표시되면 텍스트 상자에 이름을 입력한 다음 단추를 클릭하여 이름을 추가할 수 있습니다.
관련 콘텐츠
.NET Desktop feedback