32
Introduction to XAML Kim, Hyunyoung ([email protected]) Digital Media Lab. 2010-07-07

Introduction To Xaml

  • Upload
    phoooo

  • View
    1.651

  • Download
    1

Embed Size (px)

DESCRIPTION

Charles Petzold's WPF Chapter 19-20

Citation preview

Page 1: Introduction To Xaml

Introduction to XAML

Kim, Hyunyoung ([email protected])Digital Media Lab.

2010-07-07

Page 2: Introduction To Xaml

Keywords• WPF• XML• XAML• Window 엘리먼트• 프로퍼티• 약간은 불필요한 시도

Page 3: Introduction To Xaml

19 장 XAML

Page 4: Introduction To Xaml

XAML [zæ:mɛl]

• WPF (Window Presentation Foundation)– 인터페이스와 비즈니스 로직을 분명히 구분– 응용 프로그램 서비스의 호스트를 통일 : 인터페이스 , 애니메이션 , 3D, 오디오 등

• XML (Extensible Markup Language)

• XAML (Extensible Application Markup Language)– 마이크로소프트에서 구조값과 객체를 초기화하는데 사용하기 위해 만든 선언형 XML 기반 언어– WPF 의 사용자 인터페이스를 위한 언어– 런타임 속성– 편집 도구의 자유 : 비주얼 스튜디오 , 익스프레션 블렌드 , 메모장– 의사소통 : 개발자와 디자이너 간에 콘텐츠를 자유롭게 공유하고 편집 가능– C# 코드로 표현 가능– System.Windows.Controls

<Button Foreground=“Yellow” FontSize=“24pt”>Hello, XAML!

</Button>

Button btn = new Button();btn.Foreground = Brushes.Yellow;btn.FontSize = 32; // 장치 독립적 단위btn.Content = “Hello, XAML!”

Page 5: Introduction To Xaml

Stand Alone XAML

• 두 문서에 같은 엘리먼트 이름을 서로 다른 목적으로 사용하는 경우– WPF 프로그래머의 XAML 문서 & 셔츠 버튼 제조업자의 XML 문서

xmlns: XML 네임스페이스 속성– 엘리먼트와 자식 엘리먼트에게 적용– 유일하고 영속적 , URL 을 사용하는 것이 일반적

• 예제 XamlStackPanel.xaml• PresentationHost.exe

– 인터넷 익스플로러에 의해 호스팅될 수 있는 Page 타입의 객체를 생성– 로드된 XAML 을 실제 StackPanel, Button 등 객체로 변환한 후 이 객체를 Page 의 컨텐트 프로퍼티에 저장

http://schemas.microsoft.com/winfx/2006/xaml/presentation

<Button Foreground=“Yellow” FontSize=“24pt”>Hello, XAML!

</Button>

Page 6: Introduction To Xaml

페이지 속성 변경• 예제 XamlPage.xaml

– Page 를 루트 엘리먼트로 생성하고 WindowTitle 프로퍼티에 원하는 텍스트를 설정– StackPanel 을 Page 의 자식으로 생성

• Window 를 루트 엘리먼트로 한 스탠드얼론 XAML 은 불가능– PresentationHost.exe 는 스탠드얼론 XAML 파일의 루트 엘리먼트를 어떤 것의 자식으로 만듦– Window 객체는 그 어떤 것의 자식도 될 수 없음– 루트 엘리먼트는 Window 를 제외하고 FrameworkElement 를 상속받는 것이면 어떤 것도 가능

Page 7: Introduction To Xaml

XamlReader.Load

• XamlReader.Load 메소드– System.Windows.Markup 네임스페이스– XAML 을 파싱해 초기화된 객체로 전환– XamlWriter.Save 는 객체로부터 XAML 을 생성– Stream 객체나 XmlReader 객체를 받음

string strXaml ="<Button xmlns='http://schemas.microsoft.com/winfx/2006/" +" xaml/presentation'" +" Foreground='LightSeaGreen' FontSize='24pt'>" +"Click me!" +"</Button>";

StringReader strreader = new StringReader(strXaml);XmlTextReader xmlreader = new XmlTextReader(strreader);object obj = XamlReader.Load(xmlreader);

Page 8: Introduction To Xaml

XAML 을 리소스로 사용하기• LoadXamlResource.xml

– Button 객체에 Name 속성 포함

• LoadXamlResource.cs

– Stream 객체가 XamlReader.Load 의 인자가 되어 반환되는 객체 (StackPanel) 를 Win-dow 의 Content 프로퍼티에 할당

– 일단 객체가 XAML 로부터 변환되어 창의 비주얼 트리의 일부가 되면 FindName 메소드를 사용해서 엘리먼트 트리상에서 특정한 이름으로 찾는 것이 가능

– 실행 시에 로드한 XAML 에게 이벤트 핸들러를 연결할 수 있는 가장 간단한 방법

<Button Name="MyButton" HorizontalAlignment="Center" Margin="24">

Hello, XAML!</Button>

Uri uri = new Uri("pack://application:,,,/LoadXamlRe-source.xml");Stream stream = Application.GetResourceStream(uri).Stream;FrameworkElement el = XamlReader.Load(stream) as FrameworkEle-ment;Content = el;

Button btn = el.FindName("MyButton") as Button;

if (btn != null)btn.Click += ButtonOnClick;

Page 9: Introduction To Xaml

Window 가 루트인 Xaml• LoadXamlWindow.xml

• LoadXamlWindow.cs

– PresentationHost.exe 는 XAML 을 어떤 것의 자식으로 변환– 여기서는 XAML 리소스가 Window 임을 인식 , Window 를 상속받거나 Window 자체를 직접

생성하지 않음– 버튼 클릭 이벤트 핸들러를 비주얼 트리 속에서 찾아 연결하지 않고 Window 의 AddHandler 를

호출해 연결– Main 메소드는 Application 의 Run 메소드에 Window 객체를 인자로 전달

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presen-tation" Title="Load Xaml Window" SizeToContent="WidthAndHeight" ResizeMode="CanMinimize">

Uri uri = new Uri("pack://application:,,,/LoadXamlWindow.xml");Stream stream = Application.GetResourceStream(uri).Stream;Window win = XamlReader.Load(stream) as Window;

win.AddHandler(Button.ClickEvent, new RoutedEventHandler(ButtonOnClick));

app.Run(win);

Page 10: Introduction To Xaml

XAML 을 C# 에서 로드하기

• 파일명은 XmlTextReader 생성자로 바로 전달

• 객체가 Window 이면 모달리스 대화상자처럼 보임

XmlTextReader xmlreader = new XmlTextReader(dlg.FileName);object obj = XamlReader.Load(xmlreader);

if (obj is Window){

Window win = obj as Window;win.Owner = this;win.Show();

}

Elseframe.Content = obj;

Page 11: Introduction To Xaml

XAML• 실제 애플리케이션에서는 XAML 을 소스 코드와 함께 컴파일 하는 것이 보편적 , 효율적

– XAML 안에 이벤트 핸들러 이름을 직접 명시 가능

• 지금까지 본 XAML– WPF 의 클래스와 프로퍼티만을 사용– 그러나 XAML 은 WPF 만을 위한 마크업 언어는 아님 ( 예 : Windows Workflow Foundation,

WPF)– http://schemas.microsoft.com/winfx/2006/xaml: XAML 명세

– WPF 에서 사용

– XAML 고유 엘리먼트와 속성을 위한 네임스페이스는 관례적으로 접두어 x 와 함께 선언– 고유 엘리먼트와 속성이 많지 않아 WPF 관련 네임스페이스가 기본

xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation

xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml/presentation

Page 12: Introduction To Xaml

Class 속성• Class 속성

– XAML 파일의 루트 엘리먼트– XAML 이 프로젝트 일부로 컴파일될 때만 사용 가능

• CompileXamlWindow.xaml

– XAML 과 비하인드 코드는 하나의 클래스

x:Class="MyNamespace.MyClasName"

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presen-tation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="Petzold.CompileXamlWindow.CompileXamlWindow">

namespace Petzold.CompileXamlWindow{

public partial class CompileXamlWindow : Window{

…}

}

Page 13: Introduction To Xaml

• BAML ( 바멜 )– XAML 의 바이너리 형태

• CompileXamlWindow.g.cs– XAML 로부터 산출된 코드– Lstbox 와 elips 가 선언– InitializeComponent()– XAML 을 코드와 함께 컴파일했을 때만 가능

public CompileXamlWindow(){

InitializeComponent(); // XAML 엘리먼트 속성 설정 , 이벤트 핸들러 연결…}

void ButtonOnClick(object sender, RoutedEventArgs args){

Button btn = sender as Button; // 생략가능…

}

Page 14: Introduction To Xaml

자신의 클래스를 XAML 내에서 사용• 다른 네임스페이스 선언

– 반드시 소문자– http: 와 유사– 사용하기 전에 선언– src ( 소스코드 ) 가 자주 쓰임

• UseCustomClass.xaml• UseCustomClass.cs

– ColorGridBox 가 상속받은 ListBox 로 바꾸면 생략가능– 데이터 바인딩을 정의하면 SelectionChanged 이벤트 핸들러를 완전히 XAML 파일 속으로

넣을 수 있음 (23 장 )

xmlns:stuff=“clr-namespace:MyNamespace”

<stuff:MyControl …>

using Petzold.SelectColorFromGrid;…void ColorGridBoxOnSelectionChanged(object sender, SelectionChangedEventArgs args){

ColorGridBox clrbox = args.Source as ColorGridBox;…

}

Page 15: Introduction To Xaml

XAML 에서 사용자 정의 클래스 정의• CenteredButton.xaml

• UseCustomXamlClass.xaml

<Button xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presen-tation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="Petzold.UseCustomXamlClass.CenteredButton" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="12" />

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presen-tation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:src="clr-namespace:Petzold.UseCustomXamlClass" x:Class="Petzold.UseCustomXamlClass.UseCustomXamlClass" Title = "Use Custom XAML Class"> <StackPanel Name="stack"> <src:CenteredButton>Button A</src:CenteredButton> <src:CenteredButton>Button B</src:CenteredButton> <src:CenteredButton>Button C</src:CenteredButton> <src:CenteredButton>Button D</src:CenteredButton> <src:CenteredButton>Button E</src:CenteredButton> </StackPanel></Window>

Page 16: Introduction To Xaml

Cont’d• UseCustomXamlClass.cs

public UseCustomXamlClass(){

InitializeComponent();

for (int i = 0; i < 5; i++){

CenteredButton btn = new CenteredButton();btn.Content = "Button No. " + (i + 1);stack.Children.Add(btn);

}}

Page 17: Introduction To Xaml

명확한 Main 이 사라지는 현상• MyApplication.xaml

– ApplicationDefinition 으로 빌드 작업 설정

– StartupUri 는 Main 함수에서 호출되는 Run 메소드를 대체 , 초기 Window 객체 띄움

• MyApplication.cs

– MyApplication.g.cs 파일에서는 Main 메소드 있음– 삭제가능

<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presen-tation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="Petzold.IncludeApplicationDefinition.MyApplication" StartupUri="MyWindow.xaml" />

namespace Petzold.IncludeApplicationDefinition{ public partial class MyApplication : Application { }}

Page 18: Introduction To Xaml

코드가 없는 프로젝트• XAML 속에 데이터 바인딩을 가지고 있는 경우• XAML 애니메이션을 사용하는 경우

• XamlOnlyApp.xaml

– 컴파일 시 클래스 자동 생성

• XamlOnlyWindow.xaml

– BAML

실제 구조는 코드를 가진 프로젝트와 유사

<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presen-tation" StartupUri="XamlOnlyWindow.xaml" />

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presen-tation" Title="Compile XAML Only" SizeToContent="WidthAndHeight" ResizeMode="CanMinimize"> <StackPanel>

… </StackPanel></Window>

Page 19: Introduction To Xaml

XAML 파일 속에 C# 코드 넣기• 앞의 CompileXamlOnly 프로젝트와 유사

• EmbeddedCodeWindow.xaml

– 필드 정의는 불가능– using 등의 문제 해결 위해 System.Reflection 네임스페이스의 클래스 숙지

<Window> <StackPanel> … <x:Code> <![CDATA[

… void ListBoxOnSelection(object sender, SelectionChangedEventArgs args) { string strItem = lstbox.SelectedItem as string; System.Reflection.PropertyInfo prop = typeof(Brushes).GetProperty(strItem); elips.Fill = (Brush)prop.GetValue(null, null); } ]]> </x:Code> </StackPanel></Window>

Page 20: Introduction To Xaml

응용• 리소스에 이미지 파일 추가

• DesignXamlButtonWindow.xaml

<Button HorizontalAlignment="Center“ VerticalAlignment="Center“ Margin="24"> <StackPanel> <Polyline Stroke="Black" Points="0 10,10 0,20 10,30 0,40 10,50 0, 60 10,70 0,80 10,90 0,100 10" />

<Image Margin="0,10,0,0" Source="BOOK06.ICO" Stretch="None" />

<Label HorizontalAlignment="Center"> _Read Books! </Label>

<Polyline Stroke="Black" Points="0 0,10 10,20 0,30 10,40 0,50 10, 60 0,70 10,80 0,90 10,100 0" /> </StackPanel></Button>

Page 21: Introduction To Xaml

20 장 프로퍼티와 속성

Page 22: Introduction To Xaml

동적 XAML Reader• XamlCruncher 프로젝트

• XamlCruncherAssemblyInfo.cs– 프로그램 정보

• XamlCruncherSettings.cs

public Dock Orientation = Dock.Left; // TextBox 와 Frame 위치제어public int TabSpaces = 4; // 탭 키를 누를 때 삽입할 공백개수public string StartupDocument = // 처음 나오는 XAML 을 설정 "<Button xmlns=\"http://schemas.microsoft.com/winfx" + "/2006/xaml/presentation\"\r\n" + " xmlns:x=\"http://schemas.microsoft.com/winfx" + "/2006/xaml\">\r\n" + " Hello, XAML!\r\n" + "</Button>\n";

// 생성자 . 폰트 지정public XamlCruncherSettings(){

FontFamily = "Lucida Console";FontSize = 10 / 0.75;

}

Page 23: Introduction To Xaml

XamlCruncher.cs• XamlCruncher.cs

– Window 의 컨텐트가 될 Grid 를 생성– Xaml 이라는 최상위 메뉴와 하위 메뉴 생성

// DockPanel 을 찾은 후 그것에서 TextBox 를 제거DockPanel dock = txtbox.Parent as DockPanel;dock.Children.Remove(txtbox);

// Grid 생성 , 3 개의 열과 행Grid grid = new Grid();dock.Children.Add(grid);

// Xaml 을 최상위 메뉴로 삽입MenuItem itemXaml = new MenuItem();itemXaml.Header = "_Xaml";menu.Items.Insert(menu.Items.Count - 1, itemXaml);

Page 24: Introduction To Xaml

Cont’dvoid Parse(){

StringReader strreader = new StringReader(txtbox.Text);XmlTextReader xmlreader = new XmlTextReader(strreader);try{

object obj = XamlReader.Load(xmlreader); // 예외 상황 발생 시

txtbox.Foreground = SystemColors.WindowTextBrush;

if (obj is Window){

// Window 객체를 위해서는 F7 키를 눌렀을 때 독립된 창을 띄워줌win = obj as Window;statusParse.Content = "Press F7 to display Window";

}else{

// Frame 컨트롤의 Content 프로퍼티에 설정win = null;frameParent.Content = obj; statusParse.Content = "OK";

}}catch (Exception exc){

// TextBox 의 텍스트 전체를 붉은색으로 표시하고 메시지를 상태표시줄에 표시txtbox.Foreground = Brushes.Red;statusParse.Content = exc.Message;

}}

Page 25: Introduction To Xaml

공백 개수 변경• XamlTabSpaceDialog.xaml

– 대화상자의 배치 정의

• XamlTabSpaceDialog.cs

• XamlCruncher.cs– Tab Space 메뉴 선택 시

위 대화상자 호출

public int TabSpaces{

set { txtbox.Text = value.ToString(); }get { return Int32.Parse(txtbox.Text); }

}void TextBoxOnTextChanged(object sender, TextChangedEventArgs args){

int result; btnOk.IsEnabled = (Int32.TryParse(txtbox.Text, out result) && result > 0 && result < 11);}void OkOnClick(object sender, RoutedEventArgs args){ DialogResult = true;}

Page 26: Introduction To Xaml

TextBox 와 Frame 의 위치 변경• XamlOrientationMenuItem.cs

Page 27: Introduction To Xaml

Star.xaml

• Points 프로퍼티– PointCollection 타입– 연속적인 X 와 Y 좌표를 포인트로 명세– 숫자는 공백이나 콤마로 구분 가능

• Fill 프로퍼티– Brushes 클래스의 정적 멤버 사용– 16 진법으로 RGB 색상 사용 가능– 알파 채널 적용 가능 (128)– 부동소수점으로 scRGB 스킴으로 표현

<Polygon xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Points="144 48, 200 222, 53 114, 235 114, 88 222" Fill="Red" Stroke="Blue" StrokeThickness="5" />

Fill=“FF0000”

Fill=“#80FF0000”

Fill=“sc#0.5,1,0,0”

Page 28: Introduction To Xaml

LinearGradientBrush• 적어도 2 개의 값과 그라디언트 스탑 필요• 객체 엘리먼트 (Polygon) & 프로퍼티 속성 (Fill)• 자식 엘리먼트를 포함하는 문법으로 프로퍼티 명세 가능 ( 프로퍼티 엘리먼트 , 속성요소 )

<Polygon> <Polygon.Fill> Red </Polygon.Fill></Polygon>

<Polygon.Fill> <Brush> Red </Brush></Polygon.Fill>

(Brush 타입의 Fill 프로퍼티 참조 )

<Polygon.Fill> <SolidColorBrush> Red </ SolidColorBrush></Polygon.Fill>

(Brush 는 SolidColorBrush 타입의 객체로 변환가능 )

<Polygon.Fill> <SolidColorBrush Color=“Red”> </ SolidColorBrush></Polygon.Fill>

(SolidColorBrush 는 객체이므로 프로퍼티 가질 수 있음 )

<!-- 잘못된 문법 -><Polygon.Fill Attr=“Whatever”> …</Polygon.Fill>

( 프로퍼티는 프로퍼티 가질 수 없음 )

Page 29: Introduction To Xaml

Cont’d<Polygon xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presen-tation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Points="144 48, 200 222, 53 114, 235 114, 88 222" Stroke="Blue" StrokeThickness="5"> <Polygon.Fill> <RadialGradientBrush> <GradientStop Offset="0" Color="Blue" /> <GradientStop Offset="1" Color="Red" /> </RadialGradientBrush> </Polygon.Fill></Polygon>

Page 30: Introduction To Xaml

윈도우 컨텐트 프로퍼티• DockPanel

• Grid

• StackPanel

Page 31: Introduction To Xaml

RoutedEvent• 클래스와 이벤트 이름으로 속성으로 사용함으로써 이벤트 핸들러 설정 가능

<TextBlock.ContextMenu><ContextMenu MenuItem.Click="MenuItemOnClick">

<MenuItem Header="Red" /> <MenuItem Header="Orange" /> <MenuItem Header="Yellow" /> <MenuItem Header="Green" /> <MenuItem Header="Blue" /> <MenuItem Header="Indigo" /> <MenuItem Header="Violet" /> </ContextMenu></TextBlock.ContextMenu>

Page 32: Introduction To Xaml

Thank you• Q&A