Sunday, May 24, 2009

Better WPF/Silverlight Development in F#: Attached Dependency Properties

A very common idiom in WPF/Silverlight is the attached property.  Attached properties are properties that only have meaning in certain contexts, usually in relation to another class.  Attached properties are everywhere in WPF/Silverlight.  Although they are widely useful they are most commonly used with layout panels.  By introducing the notion of attached properties the architects of WPF were able to avoid having to add every conceivable property for every conceivable layout panel to each control (Top, Left, Grid Column, Grid Row, Rotation, and so on).

Of course neither the CLR nor C# has any notion of attached properties.   Therefore attached properties are typically implemented using a pair of static set and get methods on the Layout class.  These static setter/getter methods use a static dictionary to link a control to its attached property value.  As an example the Canvas panel lays controls out in a Cartesian coordinate system and has a Left attached property and a Top attached property.  Specifying these properties on a control looks something like this in C#:

Canvas.SetLeft(myTextBox, 23.0); Canvas.SetTop(myTextBox,24.0); myCanvas.Children.Add(myTextBox);

This works but it isn't ideal.  For one thing attached properties are not discoverable because they do not show up in the control’s intellisense list. However the real issue though is that the code is too low-level, exposing the developer to the implementation of attached properties rather than simply letting them express their intent.

F# has the notion of extension properties.  Like extension methods in C#, extension properties can be defined on a class outside of the class definition.  So with the smallest dab of code...

type UIElement with member this.Left with get() = Canvas.GetLeft(this) and set(value) = Canvas.SetLeft(this, value) member this.Top with get() = Canvas.GetTop(this) and set(value) = Canvas.SetTop(this, value)

…I can do this…

myTextBox.Left <- 23.0 myTextBox.Top <- 24 myCanvas.Children.Add(myTextBox)

Much better.  Now the properties belong to the control but like extension methods they only appear when the assembly with Canvas is imported.  Unfortunately with the current build of F# you can't use attached properties in object expressions like this...

Image(Uri = Uri(“test.png”), Left = x * 20, Top = x * 40)

...however I've been assured by Don Syme himself that this will be fixed by VS 2010 Beta 2. 

So there you have it.  An admittedly small, but very nice trick.  More to follow.

13 comments:

Ryan Riley said...

Awesome post. A colleague and I have been discussing a DSL for working with WPF/Silverlight from code. Looks like F# could easily prove itself an perfect platform.

Anonymous said...
This comment has been removed by a blog administrator.
Anonymous said...
This comment has been removed by a blog administrator.
花蓮民宿 said...
This comment has been removed by a blog administrator.
Anonymous said...
This comment has been removed by a blog administrator.
Anonymous said...

花蓮民宿|花蓮|花蓮民宿|花蓮民宿|花蓮美食|花蓮旅遊|花蓮|花蓮民宿訂房|花蓮就業|花蓮房屋|花蓮民宿訂房諮詢|花蓮旅遊
花蓮美食|花蓮民宿|花蓮旅遊|花蓮美食|花蓮住宿|花蓮飯店|花蓮旅館|花蓮|花蓮民宿|花蓮民宿推薦|花蓮民宿市區|花蓮民宿王|花蓮民宿網|花蓮民宿資訊網|花蓮民宿悠遊網|花蓮民宿交流網|花蓮海景民宿|花蓮海邊民宿|花蓮海岸民宿|花蓮旅遊民宿|花蓮|花蓮旅遊|花蓮廣告|花蓮民宿

Mike Davies said...
This comment has been removed by a blog administrator.
Dolphin said...
This comment has been removed by a blog administrator.
Anonymous said...
This comment has been removed by a blog administrator.
Anonymous said...
This comment has been removed by a blog administrator.
Anonymous said...
This comment has been removed by a blog administrator.
Anonymous said...
This comment has been removed by a blog administrator.
Anonymous said...
This comment has been removed by a blog administrator.

About Me

My photo
I'm a software developer who started programming at age 16 and never saw any reason to stop. I'm working on the Presentation Platform Controls team at Microsoft. My primary interests are functional programming, and Rich Internet Applications.