업데이트: 2007년 11월
WPF(Windows Presentation Foundation)에서는 응용 프로그램을 만들기 위한 다양한 환경을 제공합니다. 그러나 Windows Forms 코드에 상당한 노력을 기울인 경우 이 코드를 처음부터 다시 작성하지 않고 WPF을 사용하여 기존 Windows Forms 응용 프로그램을 확장하는 것이 더 효율적일 수 있습니다. 일반적으로 WPF에서 구현한 하나 이상의 페이지를 Windows Forms 응용 프로그램 내에 포함할 수 있습니다.
이 연습에서는 Windows Forms 응용 프로그램에서 WPF 페이지를 호스팅하는 응용 프로그램에 대해 안내합니다. 이 페이지는 DLL로 패키지된 단순한 데이터 입력 응용 프로그램입니다. 이 예제는 Windows Presentation Foundation에서 Windows Forms 합성 컨트롤 호스팅 샘플과 모양 및 기능이 거의 동일하도록 디자인되었습니다. 주된 차이점은 호스팅 시나리오가 반대로 되어 있다는 것입니다.
참고
호스팅된 페이지는 엄밀한 의미에서 WPF 컨트롤이 아닙니다. 대신 DLL로 패키지된 일반적인 WPF 페이지입니다. 그러나 폼에서 WPF 컨트롤을 호스팅하는 기술은 일반 페이지 호스팅에 사용하는 기술과 동일합니다. WPF 컨트롤에 대한 자세한 내용은 컨트롤 사용자 지정을 참조하십시오.
이 연습은 두 단원으로 나뉘어져 있습니다. 첫 번째 단원에서는 WPF 페이지 구현에 대해 간략히 설명합니다. 두 번째 단원에서는 Windows Forms 응용 프로그램에서 페이지를 호스팅하고 페이지의 이벤트를 수신하고 일부 페이지 속성에 액세스하는 방법에 대해 자세히 설명합니다.
이 연습에서 수행할 작업은 다음과 같습니다.
Windows Presentation Foundation 페이지 구현
Windows Forms 호스트 응용 프로그램 구현
이 연습에서 설명하는 작업의 전체 코드 목록을 보려면 Windows Forms에서 간단한 Windows Presentation Foundation 컨트롤 호스팅 샘플을 참조하십시오.
사전 요구 사항
이 연습을 완료하려면 다음 구성 요소가 필요합니다.
- Visual Studio 2008.
Windows Presentation Foundation 페이지 구현
이 예제에서 사용되는 WPF 페이지는 사용자의 이름과 주소를 입력하는 간단한 데이터 입력 폼입니다. 사용자가 작업이 완료되었음을 나타내는 두 개의 단추 중 하나를 클릭하면 페이지에서 사용자 지정 이벤트가 발생하여 해당 정보를 호스트에 반환합니다. 이 페이지는 연습: Windows Presentation Foundation에서 Windows Forms 합성 컨트롤 호스팅에서 사용하는 Windows Forms 컨트롤과 형태 및 기능이 거의 동일합니다. Windows Forms 폼에서 이 페이지를 호스팅하기 위해 페이지를 사용자 지정할 것은 특별히 없습니다. 이 페이지를 Frame 또는 더 큰 WPF 페이지로 쉽게 로드할 수 있습니다. 다음 그림에서는 렌더링된 페이지를 보여 줍니다.
Windows Presentation Foundation 페이지
프로젝트 만들기
프로젝트를 시작하려면
Microsoft Visual Studio를 시작하고 새 프로젝트 대화 상자를 엽니다.
WPF 브라우저 응용 프로그램 템플릿을 선택합니다.
새 프로젝트의 이름을 MyControls로 지정하고 간편한 이름의 최상위 폴더(예: WfHostingWpf)에 이 프로젝트를 저장합니다. 나중에 호스트 응용 프로그램도 이 폴더에 넣습니다. 확인을 클릭하여 프로젝트를 만듭니다. 기본 프로젝트에는 Page1이라는 페이지 하나가 포함되어 있습니다.
솔루션 탐색기에서 프로젝트 이름을 마우스 오른쪽 단추로 클릭하고 속성을 선택합니다.
출력 형식을 클래스 라이브러리로 설정하여 페이지를 DLL로 컴파일합니다.
프로젝트에서 응용 프로그램 정의 파일 MyApp.xaml 및 MyApp.xaml.cs를 삭제합니다. 이러한 파일은 페이지를 응용 프로그램으로 구현하는 경우에만 필요합니다.
참고
WPF 응용 프로그램을 클래스 라이브러리로 컴파일할 경우 이 응용 프로그램을 시작하여 렌더링된 페이지를 볼 수 없습니다. 따라서 응용 프로그램이 완전히 구현되기 전까지는 출력 형식을 "Windows 응용 프로그램"으로 두는 것이 편리할 수 있습니다. 그러면 응용 프로그램을 시작하여 페이지 모양을 확인할 수 있습니다. 페이지 모양이 마음에 들면 응용 프로그램 정의 파일을 삭제하고 출력 형식을 "클래스 라이브러리"로 변경하여 DLL로 컴파일합니다.
이 프로젝트에서는 다음 시스템 DLL에 대한 참조를 포함해야 합니다. 이러한 DLL이 기본적으로 포함되지 않는 경우 프로젝트에 추가합니다.
시스템
PresentationCore
PresentationFramework
WindowsBase
페이지의 사용자 인터페이스 구현
WPF 페이지의 UI(사용자 인터페이스)는 XAML(Extensible Application Markup Language)을 사용하여 구현됩니다. 이 사용자 인터페이스는 연습: Windows Presentation Foundation에서 Windows Forms 합성 컨트롤 호스팅에서 설명하는 Windows Forms 컨트롤과 모양과 기능이 비슷하도록 디자인합니다. 페이지의 데이터 입력 UI는 다섯 개의 TextBox 요소로 구성됩니다. 각 TextBox 요소에는 레이블로 사용되는 TextBlock 요소가 연결됩니다. 페이지 아래쪽에는 확인 및 취소라는 두 개의 Button 요소가 있습니다. 사용자가 이 단추 중 하나를 클릭하면 페이지에서 사용자 지정 이벤트가 발생하여 호스트에 정보를 반환합니다.
기본 레이아웃
다양한 UI 요소가 Grid 요소에 포함됩니다. Grid를 사용하면 HTML의 Table 요소와 같은 방법으로 페이지의 내용을 정렬할 수 있습니다. WPF에는 Table 요소도 있지만 Grid 요소가 더 가볍고 단순한 레이아웃 작업에 보다 적합합니다.
다음 예제에서는 기본 레이아웃 코드를 보여 줍니다. 이 코드에서는 Grid 요소에서 열 및 행 수를 지정하여 페이지의 전체 구조를 정의합니다. Page1.xaml의 코드를 이 코드로 바꿉니다.
<Grid xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
x:Class="MyControls.Page1"
Background="#DCDCDC"
Width="375"
Height="250"
Name="rootElement"
Loaded="Init">
...
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
표에 TextBlock 및 TextBox 요소 추가
표 요소의 RowProperty 및 ColumnProperty 특성을 해당 행 및 열 번호로 설정하여 표에서 UI 요소를 배치합니다. 행 및 열 번호는 0부터 시작합니다. 요소의 ColumnSpanProperty 특성을 설정하면 요소가 여러 열에 걸쳐 있을 수 있습니다. Grid 요소에 대한 자세한 내용은 방법: Grid 요소 만들기를 참조하십시오.
다음 예제에서는 페이지의 TextBox 및 TextBlock 요소를 보여 줍니다. 여기서는 요소의 RowProperty 및 ColumnProperty 특성을 설정하여 표에서 해당 요소를 적절히 배치합니다. 이 코드를 Page1.xaml에서 Grid 요소 바로 아래에 추가합니다.
<TextBlock Grid.Column="0"
Grid.Row="0"
Grid.ColumnSpan="4"
Margin="10,5,10,0"
HorizontalAlignment="Center"
Style="{StaticResource titleText}">Simple WPF Control</TextBlock>
<TextBlock Grid.Column="0"
Grid.Row="1"
Style="{StaticResource inlineText}"
Name="nameLabel">Name</TextBlock>
<TextBox Grid.Column="1"
Grid.Row="1"
Grid.ColumnSpan="3"
Name="txtName"/>
<TextBlock Grid.Column="0"
Grid.Row="2"
Style="{StaticResource inlineText}"
Name="addressLabel">Street Address</TextBlock>
<TextBox Grid.Column="1"
Grid.Row="2"
Grid.ColumnSpan="3"
Name="txtAddress"/>
<TextBlock Grid.Column="0"
Grid.Row="3"
Style="{StaticResource inlineText}"
Name="cityLabel">City</TextBlock>
<TextBox Grid.Column="1"
Grid.Row="3"
Width="100"
Name="txtCity"/>
<TextBlock Grid.Column="2"
Grid.Row="3"
Style="{StaticResource inlineText}"
Name="stateLabel">State</TextBlock>
<TextBox Grid.Column="3"
Grid.Row="3"
Width="50"
Name="txtState"/>
<TextBlock Grid.Column="0"
Grid.Row="4"
Style="{StaticResource inlineText}"
Name="zipLabel">Zip</TextBlock>
<TextBox Grid.Column="1"
Grid.Row="4"
Width="100"
Name="txtZip"/>
UI 요소 스타일 지정
데이터 입력 폼의 요소는 대부분 모양이 비슷합니다. 즉, 이러한 요소의 여러 속성 설정이 동일합니다. 이 예제 코드에서는 각 요소의 특성을 따로 설정하지 않고 Style 요소를 사용하여 요소의 클래스에 대한 표준 속성 설정을 정의합니다. 이 방법을 사용하면 페이지의 복잡도를 줄이고 하나의 스타일 특성을 통해 여러 요소의 모양을 변경할 수 있습니다.
Style 요소는 Grid 요소의 Resources 속성에 포함되어 있으므로 페이지의 모든 요소에서 사용할 수 있습니다. 스타일의 이름을 지정하는 경우 요소에 스타일을 적용하려면 Style 요소 집합을 해당 스타일 이름에 추가합니다. 이름을 지정하지 않은 스타일은 요소의 기본 스타일이 됩니다. WPF 스타일에 대한 자세한 내용은 스타일 지정 및 템플릿을 참조하십시오.
다음 예제에서는 WPF 페이지의 Style 요소를 보여 줍니다. 이 코드를 Page1.xaml에서 Grid 요소 바로 아래에 추가합니다. 스타일이 요소에 어떻게 적용되는지 확인하려면 앞의 코드 예제를 참조하십시오. 예를 들어 마지막 TextBlock 요소는 inlineText 스타일을 사용하고 마지막 TextBox 요소는 기본 스타일을 사용합니다.
<Grid.Resources>
<Style x:Key="inlineText" TargetType="{x:Type TextBlock}">
<Setter Property="Margin" Value="10,5,10,0"/>
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="FontSize" Value="12"/>
</Style>
<Style x:Key="titleText" TargetType="{x:Type TextBlock}">
<Setter Property="DockPanel.Dock" Value="Top"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="Margin" Value="10,5,10,0"/>
</Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Margin" Value="10,5,10,0"/>
<Setter Property="Width" Value="60"/>
</Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Margin" Value="10,5,10,0"/>
</Style>
</Grid.Resources>
확인 및 취소 단추 추가
페이지의 마지막 요소는 확인 및 취소Button 요소입니다. 이들 요소는 Grid의 마지막 행에서 처음 두 열을 사용합니다. 이러한 요소에서는 공용 이벤트 처리기 ButtonClicked와 앞의 코드 예제에서 정의한 기본 Button 스타일을 사용합니다. 다음 코드를 Page1.xaml에서 마지막 TextBox 요소 바로 아래에 추가합니다. 이것으로 페이지의 XAML 부분을 완료했습니다.
<Button Grid.Row="5"
Grid.Column="0"
Name="btnOK"
Click="ButtonClicked">OK</Button>
<Button Grid.Row="5"
Grid.Column="1"
Name="btnCancel"
Click="ButtonClicked">Cancel</Button>
페이지의 코드 숨김 파일 구현
WPF 페이지의 코드 숨김 파일 Page1.xaml.cs에서는 다음과 같은 네 가지 필수 작업을 구현합니다.
페이지의 DLL 이름을 Application 개체에 등록하여 페이지를 로드할 위치를 알려 줍니다.
사용자가 단추 중 하나를 클릭할 때 발생하는 이벤트를 처리합니다.
TextBox 요소에서 데이터를 검색하고 그 결과를 사용자 지정 이벤트 인수 개체에 패키지합니다.
OnButtonClick 이벤트를 발생시켜 사용자가 완료했음을 호스트에 알리고 데이터를 다시 호스트에 전달합니다.
또한 페이지에서는 페이지 모양을 제어하는 데 사용할 수 있는 많은 수의 색 및 글꼴 속성을 노출합니다. Windows Forms 컨트롤을 호스팅하는 데 사용되는 WindowsFormsHost 클래스와 달리 ElementHost 클래스에서는 페이지의 Background 속성만 노출합니다. 이 코드 예제와 연습: Windows Presentation Foundation에서 Windows Forms 합성 컨트롤 호스팅에서 설명하는 예제 사이의 유사성을 유지하기 위해 이 페이지에서는 나머지 속성을 직접 노출합니다.
코드 숨김 파일의 기본 구조
코드 숨김 파일은 하나의 네임스페이스 MyControls로 구성되며, 이 네임스페이스는 Page1 및 MyControlEventArgs라는 두 개의 클래스를 포함합니다. Page1.xaml.cs의 코드를 다음 코드로 바꿉니다.
using System;
using System.Windows;
using System.Windows.Navigation;
using System.Windows.Controls;
using System.Windows.Media;
namespace MyControls
{
public partial class Page1 : Grid
{
//...
}
public class MyControlEventArgs : EventArgs
{
//...
}
}
첫 번째 클래스 Page1은 Page1.xaml에서 정의한 UI의 기능을 구현하는 코드를 포함하는 partial 클래스입니다. Page1.xaml을 구문 분석할 때 XAML이 동일한 partial 클래스로 변환되고 두 partial 클래스가 병합되어 컴파일된 페이지를 형성합니다. 따라서 코드 숨김 파일의 코드 이름이 Page1.xaml에 할당된 클래스 이름과 일치해야 하며 페이지의 루트 요소에서 상속해야 합니다. 두 번째 클래스 MyControlEventArgs는 데이터를 다시 호스트에 보내는 데 사용되는 이벤트 인수 클래스입니다.
Page1 클래스 초기화
다음 코드 예제에서는 다음과 같은 몇 가지 기본 작업을 구현합니다.
Private 이벤트 OnButtonClick 및 관련 대리자 MyControlEventHandler를 선언합니다.
사용자 데이터를 저장하는 여러 private 전역 변수를 만듭니다. 이 데이터는 해당 속성을 통해 노출됩니다.
페이지의 Loaded 이벤트에 대한 Init 처리기를 구현합니다. 이 처리기에서는 Page1.xaml에서 정의한 값을 할당하여 전역 변수를 초기화합니다. 이를 위해 일반적인 TextBlock 요소 nameLabel에 할당된 Name을 사용하여 해당 요소의 속성 설정에 액세스합니다.
다음 코드를 Page1 클래스에 추가합니다.
public partial class Page1 : Grid
{
public delegate void MyControlEventHandler(object sender, MyControlEventArgs args);
public event MyControlEventHandler OnButtonClick;
private FontWeight _fontWeight;
private double _fontSize;
private FontFamily _fontFamily;
private FontStyle _fontStyle;
private SolidColorBrush _foreground;
private SolidColorBrush _background;
private void Init(object sender, EventArgs e)
{
//They all have the same style, so use nameLabel to set initial values.
_fontWeight = nameLabel.FontWeight;
_fontSize = nameLabel.FontSize;
_fontFamily = nameLabel.FontFamily;
_fontStyle = nameLabel.FontStyle;
_foreground = (SolidColorBrush)nameLabel.Foreground;
_background = (SolidColorBrush)rootElement.Background;
}
단추의 클릭 이벤트 처리
사용자는 페이지 맨 아래에 있는 확인 단추나 취소 단추를 클릭하여 데이터 입력 작업을 완료했음을 표시합니다. 두 단추에서는 모두 동일한 Click 이벤트 처리기 ButtonClicked를 사용합니다. 두 단추의 이름은 btnOK 또는 btnFalse입니다. 처리기에서 sender 인수의 값을 검사하여 어떤 단추가 클릭되었는지 확인할 때 이 이름을 사용합니다. 처리기에서 수행하는 작업은 다음과 같습니다.
페이지의 TextBox 요소의 데이터를 포함하는 MyControlEventArgs 개체를 만듭니다.
사용자가 취소 단추를 클릭하면 MyControlEventArgs 개체의 IsOK 속성을 false로 설정합니다.
OnButtonClick 이벤트를 발생시켜 사용자가 완료했음을 호스트에 알리고 수집한 데이터를 다시 전달합니다.
다음 코드를 Page1 클래스에서 Init 메서드 아래에 추가합니다.
private void ButtonClicked(object sender, RoutedEventArgs e)
{
MyControlEventArgs retvals = new MyControlEventArgs(true,
txtName.Text,
txtAddress.Text,
txtCity.Text,
txtState.Text,
txtZip.Text);
if (sender == btnCancel)
{
retvals.IsOK = false;
}
if (OnButtonClick != null)
OnButtonClick(this, retvals);
}
속성 만들기
클래스의 나머지 부분에서는 위에서 설명한 전역 변수에 해당하는 속성을 노출하기만 합니다. 속성이 변경되면 set 접근자가 해당 요소 속성을 변경하고 기본 전역 변수를 업데이트하여 페이지 모양을 수정합니다.
Page1 클래스에 다음 코드를 추가합니다.
public FontWeight MyControl_FontWeight
{
get { return _fontWeight; }
set
{
_fontWeight = value;
nameLabel.FontWeight = value;
addressLabel.FontWeight = value;
cityLabel.FontWeight = value;
stateLabel.FontWeight = value;
zipLabel.FontWeight = value;
}
}
public double MyControl_FontSize
{
get { return _fontSize; }
set
{
_fontSize = value;
nameLabel.FontSize = value;
addressLabel.FontSize = value;
cityLabel.FontSize = value;
stateLabel.FontSize = value;
zipLabel.FontSize = value;
}
}
public FontStyle MyControl_FontStyle
{
get { return _fontStyle; }
set
{
_fontStyle = value;
nameLabel.FontStyle = value;
addressLabel.FontStyle = value;
cityLabel.FontStyle = value;
stateLabel.FontStyle = value;
zipLabel.FontStyle = value;
}
}
public FontFamily MyControl_FontFamily
{
get { return _fontFamily; }
set
{
_fontFamily = value;
nameLabel.FontFamily = value;
addressLabel.FontFamily = value;
cityLabel.FontFamily = value;
stateLabel.FontFamily = value;
zipLabel.FontFamily = value;
}
}
public SolidColorBrush MyControl_Background
{
get { return _background; }
set
{
_background = value;
rootElement.Background = value;
}
}
public SolidColorBrush MyControl_Foreground
{
get { return _foreground; }
set
{
_foreground = value;
nameLabel.Foreground = value;
addressLabel.Foreground = value;
cityLabel.Foreground = value;
stateLabel.Foreground = value;
zipLabel.Foreground = value;
}
}
데이터를 다시 호스트에 보내기
파일의 마지막 구성 요소는 수집한 데이터를 호스트에 다시 보내는 데 사용되는 MyControlEventArgs 클래스입니다. MyControls 네임스페이스에 다음 코드를 추가합니다. 구현 방법은 간단하므로 자세히 설명하지 않습니다.
public class MyControlEventArgs : EventArgs
{
private string _Name;
private string _StreetAddress;
private string _City;
private string _State;
private string _Zip;
private bool _IsOK;
public MyControlEventArgs(bool result,
string name,
string address,
string city,
string state,
string zip)
{
_IsOK = result;
_Name = name;
_StreetAddress = address;
_City = city;
_State = state;
_Zip = zip;
}
public string MyName
{
get { return _Name; }
set { _Name = value; }
}
public string MyStreetAddress
{
get { return _StreetAddress; }
set { _StreetAddress = value; }
}
public string MyCity
{
get { return _City; }
set { _City = value; }
}
public string MyState
{
get { return _State; }
set { _State = value; }
}
public string MyZip
{
get { return _Zip; }
set { _Zip = value; }
}
public bool IsOK
{
get { return _IsOK; }
set { _IsOK = value; }
}
}
Windows Forms 호스트 응용 프로그램 구현
Windows Forms 호스트 응용 프로그램은 ElementHost 개체를 사용하여 폼에서 WPF 페이지를 호스팅합니다. 이 응용 프로그램에서는 페이지의 OnButtonClick 이벤트를 처리하여 폼에서 데이터를 수신합니다. 또한 페이지 모양을 수정하는 데 사용할 수 있는 옵션 단추 집합도 포함합니다. 다음 스크린 샷에서는 렌더링된 폼을 보여 줍니다.
Windows Forms 응용 프로그램에서 호스팅한 Windows Presentation Foundation 페이지
프로젝트 만들기
프로젝트를 시작하려면
Visual Studio를 시작하고 새 프로젝트 대화 상자를 엽니다.
Windows Forms 응용 프로그램 템플릿과 함께 C# 프로젝트를 선택합니다.
새 프로젝트의 이름을 WFHost로 지정하고 MyControls 프로젝트가 포함된 동일한 최상위 폴더에 프로젝트를 저장합니다. 확인을 클릭하여 프로젝트를 만듭니다.
또한 WPF 페이지를 포함하는 DLL에 대한 참조도 추가해야 합니다.
솔루션 탐색기에서 프로젝트 이름을 클릭하고 참조 추가를 선택합니다.
찾아보기 탭을 클릭하고 MyControls.dll이 들어 있는 폴더로 이동합니다.
MyControls.dll을 선택하고 확인을 클릭하여 참조 목록에 이 DLL을 추가합니다.
솔루션 탐색기에서 WindowsFormsIntegration.dll이라는 WindowsFormsIntegration 어셈블리에 대한 참조를 추가합니다.
폼의 사용자 인터페이스 디자인 구현
Windows Forms 디자이너를 열고 Windows Forms 호스트 응용 프로그램 구현에 나와 있는 그림과 같이 표시되도록 폼을 배치합니다.
컨트롤 및 WPF 페이지에 맞게 기본 폼을 확장합니다.
WPF 페이지를 보관할 폼의 오른쪽 위 모퉁이에 System.Windows.Forms.Panel 컨트롤을 추가합니다.
그림과 같이 여섯 개의 System.Windows.Forms.RadioButton 컨트롤 집합을 추가합니다.
그림과 같이 폼의 오른쪽 아래 모퉁이에 다섯 개의 System.Windows.Forms.Label 컨트롤을 추가합니다. 이러한 컨트롤은 WPF 컨트롤에서 반환하는 데이터의 레이블로 사용됩니다.
앞 단계에서 추가한 각 Label 컨트롤의 오른쪽에 Label 컨트롤을 추가합니다. 각 컨트롤의 Text 속성을 ""로 설정합니다. 이러한 컨트롤에서는 WPF 컨트롤에서 반환하는 데이터를 표시합니다.
마지막 두 단계의 컨트롤 그룹에 대한 제목으로 사용할 또 하나의 Label 컨트롤을 추가합니다. 이 Label은 그룹의 제목으로 사용하기 위한 것이므로 글꼴을 그룹의 컨트롤보다 2포인트 크게 만듭니다.
폼 초기화
일반적으로 폼의 Load 이벤트 처리기에서 호스팅 코드를 구현합니다. Windows Forms 디자이너에서 폼을 두 번 클릭하여 Load 이벤트 처리기를 만듭니다. 다음 코드 예제에서는 샘플의 Load 이벤트 처리기, WPF 페이지의 Loaded 이벤트에 대한 처리기 및 나중에 사용하는 여러 전역 변수에 대한 선언을 보여 줍니다. Form1.cs의 코드를 다음 코드로 바꿉니다.
partial class Form1 : Form
{
private ElementHost ctrlHost;
private MyControls.Page1 wpfAddressCtrl;
System.Windows.FontWeight initFontWeight;
double initFontSize;
System.Windows.FontStyle initFontStyle;
System.Windows.Media.SolidColorBrush initBackBrush;
System.Windows.Media.SolidColorBrush initForeBrush;
FontFamily initFontFamily;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
ctrlHost = new ElementHost();
ctrlHost.Dock = DockStyle.Fill;
panel1.Controls.Add(ctrlHost);
wpfAddressCtrl = new MyControls.Page1();
wpfAddressCtrl.InitializeComponent();
ctrlHost.Child = wpfAddressCtrl;
wpfAddressCtrl.OnButtonClick +=
new MyControls.Page1.MyControlEventHandler(
avAddressCtrl_OnButtonClick);
wpfAddressCtrl.Loaded += new RoutedEventHandler(
avAddressCtrl_Loaded);
}
void avAddressCtrl_Loaded(object sender, EventArgs e)
{
initBackBrush = (SolidColorBrush)wpfAddressCtrl.MyControl_Background;
initForeBrush = wpfAddressCtrl.MyControl_Foreground;
initFontFamily = wpfAddressCtrl.MyControl_FontFamily;
initFontSize = wpfAddressCtrl.MyControl_FontSize;
initFontWeight = wpfAddressCtrl.MyControl_FontWeight;
initFontStyle = wpfAddressCtrl.MyControl_FontStyle;
}
앞의 코드 예제에서 Form1_Load 메서드는 WPF 컨트롤을 호스팅하는 다음과 같은 일반적인 절차를 보여 줍니다.
새 ElementHost 개체를 만듭니다.
컨트롤의 Dock 속성을 DockStyle.Fill로 설정합니다.
Panel 컨트롤의 Controls 컬렉션에 ElementHost 컨트롤을 추가합니다.
WPF 페이지의 인스턴스를 만듭니다.
ElementHost 컨트롤의 Child 속성에 페이지를 할당하여 폼에서 페이지를 호스팅합니다.
Form1_Load 메서드에서 나머지 두 줄은 처리기를 다음의 두 가지 페이지 이벤트에 연결합니다.
OnButtonClick은 페이지에서 사용자가 확인 또는 취소 단추를 클릭할 때 발생하는 사용자 지정 이벤트입니다. 이 이벤트를 처리하여 사용자의 응답을 수신하고 사용자가 입력하는 데이터를 수집합니다.
Loaded는 WPF 페이지가 완전히 로드되면 발생하는 표준 이벤트입니다. 이 샘플에서는 페이지의 속성을 사용하여 여러 전역 변수를 초기화해야 하기 때문에 이 이벤트가 사용됩니다. 폼의 Load 이벤트가 발생할 때는 페이지가 완전히 로드되지 않았으므로 이 값은 여전히 null로 설정되어 있습니다. 이러한 속성에 액세스할 수 있으려면 페이지의 Loaded 이벤트가 발생할 때까지 기다려야 합니다.
Loaded 이벤트 처리기는 앞의 코드 예제에 나와 있습니다. OnButtonClick 처리기는 다음 단원에서 설명합니다.
OnButtonClick 처리
OnButtonClick 이벤트는 사용자가 확인 또는 취소 단추를 클릭할 때 발생합니다.
이 이벤트의 처리기에서는 이벤트 인수의 IsOK 필드를 확인하여 어떤 단추를 클릭했는지 확인합니다. lbldata 변수는 앞에서 설명한 표시되지 않는 Label 컨트롤에 해당합니다. 사용자가 확인 단추를 클릭한 경우 페이지의 TextBox 컨트롤 데이터가 해당하는 Label 컨트롤에 할당됩니다. 사용자가 취소를 클릭한 경우 Text 값이 null로 설정됩니다.
Form1.cs에 다음 코드를 추가합니다. 이제 응용 프로그램을 컴파일하여 실행할 수 있습니다.
void avAddressCtrl_OnButtonClick(
object sender,
MyControls.MyControlEventArgs args)
{
if (args.IsOK)
{
lblAddress.Text = "Street Address: " + args.MyStreetAddress;
lblCity.Text = "City: " + args.MyCity;
lblName.Text = "Name: " + args.MyName;
lblState.Text = "State: " + args.MyState;
lblZip.Text = "Zip: " + args.MyZip;
}
else
{
lblAddress.Text = "Street Address: ";
lblCity.Text = "City: ";
lblName.Text = "Name: ";
lblState.Text = "State: ";
lblZip.Text = "Zip: ";
}
}
Windows Presentation Foundation 페이지 모양 수정
폼의 왼쪽에 있는 RadioButton 컨트롤을 사용하면 WPF 페이지의 전경색, 배경색 및 여러 글꼴 속성을 변경할 수 있습니다. 배경색은 ElementHost 개체에 의해 노출됩니다. 나머지 속성은 페이지의 사용자 지정 속성으로 노출됩니다.
폼에서 RadioButton 컨트롤을 두 번 클릭하여 해당 CheckedChanged 이벤트 처리기에 대한 템플릿을 만듭니다. 다음 처리기에서 코드를 추출하고 Form1.cs의 해당 처리기에 이 코드를 추가합니다.
private void radioBackgroundOriginal_CheckedChanged(object sender, EventArgs e)
{
wpfAddressCtrl.MyControl_Background = initBackBrush;
}
private void radioBackgroundLightGreen_CheckedChanged(object sender, EventArgs e)
{
wpfAddressCtrl.MyControl_Background = new SolidColorBrush(Colors.LightGreen);
}
private void radioBackgroundLightSalmon_CheckedChanged(object sender, EventArgs e)
{
wpfAddressCtrl.MyControl_Background = new SolidColorBrush(Colors.LightSalmon);
}
private void radioForegroundOriginal_CheckedChanged(object sender, EventArgs e)
{
wpfAddressCtrl.MyControl_Foreground = initForeBrush;
}
private void radioForegroundRed_CheckedChanged(object sender, EventArgs e)
{
wpfAddressCtrl.MyControl_Foreground = new System.Windows.Media.SolidColorBrush(Colors.Red);
}
private void radioForegroundYellow_CheckedChanged(object sender, EventArgs e)
{
wpfAddressCtrl.MyControl_Foreground = new System.Windows.Media.SolidColorBrush(Colors.Yellow);
}
private void radioFamilyOriginal_CheckedChanged(object sender, EventArgs e)
{
wpfAddressCtrl.MyControl_FontFamily = initFontFamily;
}
private void radioFamilyTimes_CheckedChanged(object sender, EventArgs e)
{
wpfAddressCtrl.MyControl_FontFamily = new FontFamily("Times New Roman");
}
private void radioFamilyWingDings_CheckedChanged(object sender, EventArgs e)
{
wpfAddressCtrl.MyControl_FontFamily = new FontFamily("WingDings");
}
private void radioSizeOriginal_CheckedChanged(object sender, EventArgs e)
{
wpfAddressCtrl.MyControl_FontSize = initFontSize;
}
private void radioSizeTen_CheckedChanged(object sender, EventArgs e)
{
wpfAddressCtrl.MyControl_FontSize = 10;
}
private void radioSizeTwelve_CheckedChanged(object sender, EventArgs e)
{
wpfAddressCtrl.MyControl_FontSize = 12;
}
private void radioStyleOriginal_CheckedChanged(object sender, EventArgs e)
{
wpfAddressCtrl.MyControl_FontStyle = initFontStyle;
}
private void radioStyleItalic_CheckedChanged(object sender, EventArgs e)
{
wpfAddressCtrl.MyControl_FontStyle = System.Windows.FontStyles.Italic;
}
private void radioWeightOriginal_CheckedChanged(object sender, EventArgs e)
{
wpfAddressCtrl.MyControl_FontWeight = initFontWeight;
}
private void radioWeightBold_CheckedChanged(object sender, EventArgs e)
{
wpfAddressCtrl.MyControl_FontWeight = FontWeights.Bold;
}
참고 항목
작업
연습: Windows Forms에서 Windows Presentation Foundation 합성 컨트롤 호스팅
개념
연습: Windows Presentation Foundation에서 Windows Forms 합성 컨트롤 호스팅