What's New in XAML 2009

프로그래밍 2009.05.20 21:38 Posted by 아일레프

요즘 .Net Framework 4.0 beta가 나와 관련 리뷰가 블로그 여기저기서 쏟아 지고 있다. 상황이 이렇다 보니 차기 WPF의 기능에 대해서 관심을 가지지 않을 수가 없다. What's New in the .NET Framework 4 페이지로 가보니 "In the .NET Framework 4 Beta 1, Windows Presentation Foundation (WPF) contains changes and improvements in many areas. This includes controls, graphics, and XAML." 라고 쓰여있는 것을 확인 할 수 있었다. 기대심에 What's New in Windows Presentation Foundation Version 4  페이지로 가보았다. Control, Multi-touch, Esing Function, Designer에 대한 링크와 짤막한 글이 포함되어 있었는데… 어찌된 일인지 내가 가장 궁금해했던 "XAML"에 대한 부분만 쏙 빠져있다. .. 설마 이게 끝은 아니겠지.. MSDN 쓰는 사람이 조금 바쁜가보다. 하고 생각해보았다.

 

이 적절치 않은 시점에 작년 PDC 2008에 리뷰된 차기 XAML의 기능을 살펴 보았다. 해당 내용은 Microsoft .NET Framework: Declarative Programming Using XAML 동영상으로 확인 할 수 있다. 참 오래된 이야기이다.

 

1.     Easy Object References with {x:Reference}

2.     Built-in Types

3.     Generics in XAML with x:TypeArguments

4.     Support for Arbitrary Dictionary Keys

5.     Use of Non-Default Constructors with x:Arguments

6.     Use of Static Factory Methods with x:FactoryMethod

 

1 {x:Reference}이다. Markup Extension은 반드시, , 꼭 필요하다. 빨리 빨리 하루빨리 추가 해다오.

<Button Name="button" /> 

<Label Target="{Binding ElementName=button}"/>

 

위 코드는 Label Target Property button이름으로 XAML상에서 정의된 button이라는 객체의 reference를 넣는 구문이다. … 그런데 정말 그런가? 사실 이미 정의된 객체의 reference Target Property에 넣는 단순한 작업을 하기 위해 위 코드는 복잡한 일을 하고 있다. 그 이유는 Binding이라는 Markup Extension이 반환하는 객체는 button 객체의 reference가 아니라 BindingExpression이기 때문이다. 물론 Path가 지정되어있지 않기 때문에 결국 reference가 반환되는 것과 동일한 효과를 가지지만 좀 떨떠름하다. 그리고 더 중요한 이유가 있으니 바로… Binding MarkupExtension 이 반환하는 것이 BindingExpression 객체 이기 때문에 이 구문을 사용할 때 Target은 반드시 의존 프로퍼티여야한다는 것이다. 이 사실에 얼마나 분개해 왔던가. 왜 진작 {x:Reference}와 같은 것을 MS는 생각하지 못하고 이제서야 추가한단 말인가. 하여간 추가 해준다니 감지덕지할 뿐이다.

 

   사족 :: 제가 {x:reference}에 대한 필요성을 가장 크게 느낄 때는 Converter ConverterParameter xaml에 정의된 element의 참조를 넘겨 주고 싶을 때, 그리고 새롭게 정의한 MarkupExtension Constructor Parameter xaml에 정의된 element의 참조를 넘겨주고 싶을 때였습니다. 그리고 오늘 제 옆자리에 계신 분도 이 키워드의 필요성을 강하게 느겼다고 합니다.

 

 

2번이다. Built-In Type이다. 이젠 불필요하게 mscorlib System namespace xmlns 에 추가해주지 않아도 XAML namespace를 이용해 다양한 Type을 곧바로 사용할 수 있다. 제법 많구나.

<x:Object/><x:Boolean/><x:Char/><x:String/><x:Decimal/><x:Single/><x:Double/><x:Int16/><x:Int32/><x:Int64/>

<x:TimeSpan/><x:Uri/><x:Byte/><x:Array/><x:List/><x:Dictionary/>


Element 뿐 아니라 MarkupExtension도 허용해 주었으면 좋겠다. 예를 들어 Button ContentInt32 Type 12라는 value를 넣고자 한다면

 

<Button>

<x:Int32>12</x:Int32>

</Button>

 

이것 뿐 아니라 다음과 같이 사용할 수도 있도록 해주면 더 좋겠다.

<Button Content="{x:Int32 12}"/>

 

 

3 Generics in XAML 이녀석도 엄청나게 유용할 것 같다. 다음과 같이 사용할 수 있단다.

 

<ObservableCollection x:TypeArguments="{x:Type Employee}">
   
<l:Employee FirstName="John" Name="Doe" />
   
<l:Employee FirstName="Tim" Name="Smith" />
</ObservableCollection />

 

위 녀석은 다음코드와 같은 의미를 지니게 된다. 벌써 부터 기대된다. 흐흐흐

 

var collection = new ObservableCollection<Employee>();

collection.Add(new Employee{FirstName="John", Name="Doe"});

collection.Add(new Employee{FirstName="Tim", Name="Smith"});

 

 

4 Arbitrary Dictionary Keys string이 아닌 다른 Type Value x:Key에 지정 할 수 있다는 것인데 이것은 PDC에서 다음과 같은 예를 통해 설명되었다.

 

<StreamGeometry>M 0 0 L 12 8 l 9 12 z
   
<x:Key><x:Double>10.0</x:Double></x:Key>
</StreamGeometry>

 

사실  x:Key string이 아닌 Value를 사용할 수 있다는 것 보다 x:Key 키워드를 Element로 사용할 수 있다는 사실이 재미있다.

 

5x:Arguments 이 기능도 유용하게 사용될 수 있을 것 같다. 이 기능으로 인해 XAML 내에서 default constructor를 가지지 않는 Object도 정의할 수 있다. 정말 감사할 뿐이다.. 
 

<DateTime>
   
<x:Arguments>
       
<x:Int64>100</x:Int64>
   
</x:Arguments>
</DateTime>


여러 개의
Arguments를 사용하는 경우도 당연히 허용되어야 할 것이다. 이는 argument 라는 단어에 "s"자가 붙은것으로 봐 당연히 허용 될 것으로 보인다. 그리고 MarkupExtension도 꼭 만들어 줬으면 좋겠다.

 

 

6 x:FactoryMethod 이에 대한 예는 다음과 같다.

 

<Guid x:FactoryMethod="Guid.NewGuid" />

이는 Guid guid = Guid.NewGuid();와 동일한 의미를 가진다. x:FactoryMethod는 그 단어 대로 static factory 메소드를 호출하게 사용된다.  그런데 MarkupExtension이 추가되지 않는한 Property지정에 사용할 수는 없을 것 같다. 만약 MarkupExtension이 있다면 다음과 같이 사용될 수 있을 것이다.

 

<local:MyObject Guid="{x:FactoryMethod Guid.NewGuid}"/> --> 이건 안되는 코드. 단지 바램일 뿐.

 

.. 위와 같이 사용 가능하다면 내친김에 static factory 메소드 뿐아니라 그냥 static method도 범용적으로 사용가능하게 만들면 더욱 더 좋을 것 같다.

 

 

 

위가 XAML PDC 2008에 발표된 XAML namespace에 추가된 키워드를 소개한 것이다.

 

또 괜찮은게 있는데 훨씬 더 다양한 기능을 제공하는 XamlReader이다. 기존의 XamlReader Load, Parse 기능만 가지고 있던 것을 생각하면 이건 정말 훌륭하다. 모르긴 몰라도 XamlReader를 사용한 다양한 응용들이 Web상에 돌아다니게 될 것이다.

 

이에 추가로 몇가지 바램이 있다.

 

1.     Style을 지정할 때 Base 클래스의 Target Type지정으로 Base 클래스를 상속받는 객체들의 Style이 지정되게 해달라.

 

<Style TargetType = "{x:Type Control}">

<Setter Property="Background" Value="Black"/>

</Style>

 

위 와 같은 경우 XAML내에서 Control을 상속받는 모든 Element가 이 Style이 적용 되게끔 해줬으면 좋겠다.

 

2.     DataContext Type지정으로 Binding Source Type에 따라 Path를 정의할 때 CompileTime에 에러체크가 가능하게 해달라.

Binding이 유용하긴 하지만 CompileTime Path에 올바른 값이 들어갔는지 확인 할 수 없고 런타임에도 Exception을 먹어버린다.

<Button Content="{Binding Path=오타}"/>라고 했을 때 Binding Source로 지정된 객체(이 때는 Button 객체의 DataContext가 될 것이다.) "오타"라는 Property가 존재하지 않음에도 CompileTime과 심지어 Runtime에도 이 사실을 알 수 없다는 것은 조금 아쉽다.

x:TypeArguments 키워드도 생겼는데 이왕 Generic Binding 객체도 만들어 버려서 이를 사용할 경우에는 CompileTime이나 Design Time Path를 검사해 에러나 Exception을 발생시켜주면 바랄 바가 없다.

 

<Button Content="{Binding x:TypeArguments={x:Type local:MyObject}, Path=오타}"/> 

 

3.     Resource내에서도 MarkupExtension을 선언할 수 있게 해달라.

.. 이건 좀 힘들다는 것은 알고 있다. 그래도 이게 되면 많이 유용할 것 같은데 어떻게 좀 해주면 안될까?

<Page>

<Page.Resources>

<Binding Path="PropertyName" x:Key="myBinding"/>

</Page.Resources>

</Page>

 

위와 같이 Resource에서 Binding을 미리 정의해놓고 코드에서 불러 사용 할 수 있으면 참 좋을 것 같다. 물론... 이건 힘들다는 것을 알고는 있지만 좀  고려해달라. 아니면 MarkupExtension이 아닌 Binding 클래스 비슷한 녀석을 만들어 주던지.

사족 -- Binding MarkupExtension이기 때문에 위 코드는 다음과 같은 의미가 된다. 따라서 사용 불가능하다.

page.Resource = new Binding{ Path="PropertyName}.ProvideValues();

 

4.     Visual Studio Designer x:Class로 지정된 partial class가 존재할 때 최소한 생성자 만이라도 읽어 줬으면 좋겠다. 그리고 해당 Project App.xaml이 있다면 해당 xaml Resource도 좀 알아서 읽어줬으면 좋겠다.

<Page x:Class="">

<Button Content="{StaticResource 리소스키}"/>

</Page>

 

위 경우 당연히 지금 이 상황에서는 Error이다. 그러나 디자이너 넌 모르고 있다. InitializeComponent로 이 XAML 파일이 로드되기 전에 behind 코드에서 "리소스키"라는 key로 특정 객체가 Page Resource에 추가되어 있을 수도 있다는 것을...

 

5.     왜 유용한 기능을 가지고 있는 Class들은 모두 internal로 되어있는 것인가? 특히 System.Windows.Markup namespace의 많은 Class들을 사용할 수 있게 해주었으면 좋겠다.

 

 

 

이상하다 또 많은 불만 사항이 있었던 것 같은데… 생각날 때마다 추가해봐야겠다.

 

신고