Friday, May 22, 2009

Dynamic Xaml Upload from ClientBin


I noticed that if silverlight loads a control in xaml, which is in ClientBin folder, at run-time, XamlParseException was thrown.

Following is xaml in ClientFolder:
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:nav="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Navigation"
xmlns:telerikEditor="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Editor">










Snippet to load the xaml:
private void LoadContent(string str)
{
WebClient xmlClient = new WebClient();
xmlClient.DownloadStringCompleted += XMLFileLoaded;
xmlClient.DownloadStringAsync(new Uri(str, UriKind.RelativeOrAbsolute));
}

void XMLFileLoaded(object sender, DownloadStringCompletedEventArgs e)
{
string xmlString = e.Result;

// Got all your XML data in to a string
var uc = System.Windows.Markup.XamlReader.Load(xmlString);
var toolBar = (uc as UserControl).FindName("toolbarFile") as RadToolBar;
toolBarTray.Items.Clear();
toolBarTray.Items.Add(toolBar);
}

When I run, I got InvalidOperationException was unhandled by user code.
The error description was "Element is already the child of another element."

The reason is that RadToolBar in the xaml is a child of UserControl. So when trying to add to toolBarTray, it throws the exception.

In order to fix this problem, change the xaml file so that it looks like following:
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:nav="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Navigation"
xmlns:telerikEditor="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Editor"
x:Name="toolbarFile">








What I did was removed UserControl tag and copy all xmlns to RadToolBar tag.

And Viola!

my silverlight app runs great!

Monday, May 11, 2009

Dependency Property

닷넷 3.0부터 디펜던시 프로퍼티라는 새로운 형태의 프로퍼티가 생겼는데 Window Presentation Foundation 과 Workflow Foundation에 사용된다. 아주 유사하게 두 파운데이션에서 사용되지만 사용되는 목적은 다르다.

이 새로운 형태의 프로퍼티는 프로퍼티의 값 결정이나, 값이 변화되는 것을 시스템에 알려주거나, 데이타 바인딩을 하거나, 스타일링을 하거나, 값의 유효성을 점검하는 등등을 제공한다.
WPF에서는 UI 요소들의 프로퍼티들을 다른 모듈이나 프로그래머가 이용가능하게 노출시키는 데 사용되며 WWF에서는 Custom activities의 프로퍼티들을 노출시킨다. 노출시킨다라는 말은 속성값이 public이라서 다른 곳에서 이 프로퍼티들을 사용할 수 있다는 말이다.

이 Dependency Property를 쓰는 가장 중요한 목적은 다른 여느 프로퍼티처럼 현재의 객체의 상태를 관리하는데 있다. 하지만 기존의 .net 프로퍼티들과는 달리 로컬 프로퍼티 값이 instance variable안에 저장되지 않는다. 대신에 dependency proeperties는 dependency property framework에 등록되어있다. 그리고 사용하고 있는 프로퍼티의 값은 결정되어진다(is resolved). 즉 그 값이 조금전에 말한 프래임웍에서 프로퍼티 등록에 의한 규칙들에 의거하여 결정되어진다는 말이다.

그럼 어떻게 Dependency Property를 만들까?
첫번째로 새로만들 dependency property를 등록한다.
public static readonly DependencyProperty myProperty = DependencyProperty.Register("", typeof(), typeof());

MyProperty: 프로퍼티 이름
: 프로퍼티 자료형 예를 들면, string, int, DateTime, or any value type이나 reference type.
: 이 클래스가 새로정의된 디펜던시 프로퍼티를 가지고 있다.
그리고 WPF 프레임웍에서 어떻게 이 프로퍼티가 사용될지 정의하는 메타데이타 정보를 사용할 수도 있다. 물론 그렇게 되면 위의 예에다가 좀 더 많은 파라메타들을 정의 해야된다.
이런 메타데이타들의 종류로는
1. 각각의 element의 layout에 어떻게 이 프로퍼티가 영향을 주는 가를 나타내는 Flags.
2. 프로퍼티 값이 바뀌었을때 CallBack을 할 수 있는 이벤트 함수들(PropertyChangedCallback)
3. CoerceValueCallback
4. 값들의 적절한가를 검사하기 위한 Callbacks (ValidateValueCallback)
5. 그리고 이 프로퍼티를 위해 덧붙여지는 특징들을 지정하기위한 DependecyPropertyOptions.
1부터 4까지는 WPF를 5는 WWF를 위한 선택사항이다.

두번째로 방금전에 만든 새 프로퍼티의 setter와 getter를 만들면 됩니다.
public
{
get {return ()base.GetValue(myProperty);}
set {base.SetValue(myProperty,value);}
}