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.

.NET Language Evolution: Do you care?

Luca Bolognese recently announced that C# and VB.NET will now be co-evolved.  That is to say, no feature will be introduced to one without being added to the other.  I can't deny that this makes sense but as a language geek its certainly not very exciting news.  More ominously Luca hinted language evolution was going to "slow down."  Yikes.

ida_fossil_images

Apparently some of our customers are having difficulty ramping up on language features introduced alongside .NET 2.0.  Although I sympathize with these customers Microsoft made the right call when they took an aggressive approach towards language evolution, adding very significant new features inspired by functional languages.  Increasingly their customers are having to write scalable, asynchronous code to leverage multi-core processors.  These are hard problems and learning to think about them differently is essential to success.  There is a parallel here to the introduction of VB.NET and the phasing out of Visual Basic.

The news that C# and VB.NET evolution is going to taper off should not come as a surprise.  You can't keep adding features to a programming languages forever and it's especially hard when they have such a long heritage.  Under the circumstances Anders has done an admirable job.  Unfortunately there are certain functional algorithms that developers cannot, and will likely never be able to, express cleanly in either C# or VB.NET.

Enter F#.  Visual Studio 2010 Beta 1 is here and if you take the plunge you'll find that F# has finally been elevated to a first-class .NET language along-side C# and VB.NET.  We have every reason to believe F# will continue to evolve.  For starters it's just the first version.  Don Syme has also expressed interest in adding language features from Haskell as well.  The interesting question is: Does Language Evolution Matter?

There is some controversy over the importance of programming languages.  Some believe that it's primarily a developers knowledge of the existing class libraries that matters.  It's hard to deny this given the massive size of our libraries today.  However my personal experience is that in recent years learning the new language features introduced in C# has significantly improved my productivity, as well as the quality of my code.  It still fills me with such a sense of wonder that simply thinking about a problem differently can have such a profound effect.  It is for this reason that I've already made F# my primary language for play.  I hope to get the opportunity to use it at work at some point as well.  There are some very compelling reasons to use it to solve certain types of problems we face in WPF/Silverlight development. After all if not at Microsoft, then where? :-)

You can expect more Silverlight/WPF-related F# blog posts from me in the future.

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.