This article is meant to deeply scare you, wannabe WPF developers. Seriously, consider these facts before you enter the WPF door. For those who dare read on, here’s the full story…
Since .Net 3.0, Windows Presentation Foundation (WPF) has been proposed by Microsoft as the framework of choice for developing user interfaces. The introduction of Windows 8.0 caused a bit of panic as developers felt that WPF and .Net were going to join the fate of Silverlight, but so far there have been no signs of this. If anything, it’s clear that some form of WPF will be the UI technology of the future, either in the shape of WPF itself or its new XAML offspring. So my perception is that a developer working on microsoft systems should be well aware of these technologies. But is it easy to jump onboard? After using WPF for quite some time in different projects, I can say that unfortunately the answer is no, you are definitely not going to have a free ride this time. Why?
The language of trees: XAML
WPF uses XML files to describe the user interface. The main conceptual difference between coding a UI in c# and XAML is that c# is an imperative language, whereas XAML is a declarative one, and thus it describes more of the “what” than the “how”. C# is a list of steps in cronological order; with XAML you describe the logic containment of user interface items and let the runtime build the objects in the right order and connect them properly. C# is a sequence of steps, XAML is a tree (as XML).
From a conceptual perspective, this is all good and dandy; but there are dark sides to it.
The main trouble is that you have to learn this new XAML language. You were thinking you would be drawing shapes and panels to define your UI, and you find yourself browsing XML files. It would be great to define the visual appearance of an application by means of visual tools, but with WPF you will soon be looking at XML/XAML code.
What’s worse is that it’s not just another language with some different syntax, but a language with a different paradigm. Functional languages are considered by some as the ultimate weapon for producing bug free code in a breeze, but most developers find imperative approaches quite a bit easier to read and extend. I believe XAML is a little like a functional language.
For example, variables are a simple and well understood concept in imperative languages. With XAML, it’s not always obvious how to reference an element from another element. The situation gets surprisingly complex when you add name scopes and cross assembly references to the mix.
You’ll often be tempted to switch back to C#, as in WPF you can always choose. But even simple extensions to XAML require a fairly large amount of boilerplate code. For example, converting values for display require a small class to be written (a converter), then you need to declare an instance of this in XAML, then reference the instance in the appropriate places. All of this is really a lot of burden when you might be applying a simple formula to the input.
Another situation where the code behind temptation will be strong is when dealing with animations. Animations seem like an imperative concept more than a declarative one (animations are sequences of steps after all) so it feels natural to subscribe to events and play pause animations from handlers. Due to how animations affect properties, this is often not so straightforward. Just check the number of questions about properties being stuck on values from animations on stackoverflow.
Conclusion #1: XAML is a new language with a different syntax and paradigm compared to C# and moving code between them is not simple, so be prepared to learn and evaluate on a case by case basis what should end up in XAML and what in C#. To put it in other words, WPF with XAML is like climbing a tree with many branches, whereas c# developers are mostly used to linear code.
As I suggest in another article, an object oriented library is like a little language extension in itself. When using an OOP library, no programmer is surprised to see new domain related classes and interfaces. New classes describe the new concepts and interfaces state how the concept link to each other and are used to build systems. What is surprising, and not in a good sense, is when a library introduces new classes for basic language concepts.
WPF does this pretty regularly, and the first example is properties. Fields and properties are a well known, basic OOP tool. WPF turns this all around with specific classes to represent values in user interface objects. There are of course good reasons for all of this, but the fact that a basic language concept becomes much more complex to use is baffling. It’s especially baffling as the minds behind this architecture could have chosen for a different approach based either on language extensions or more heavily relying on programming tools, as it’s all Microsoft products and technologies.
Notifications from non user interface classes to UI are moreover handled in yet another way, by means of the INotifiable interface. Simple properties in WPF thus turn either into complex dependency properties or into INotifiable properties.
Conclusion #2: WPF as a library has a steep learning curve as it redefines even basic programming concepts. As far as properties are concerned, use dependecy properties only for UI specific configuration properties, and use INotifiable properties for signaling data model changes to the UI.
Infrastructure rich vs. feature poor
WPF clearly provides a very rich infrastructure with the XAML declarative language for UI and many new concepts and classes to learn. It supports themes, animations, transparencies, data binding. More than a simple UI library, WPF is a complex, rich application development framework. On the other hand, considering what you get with WPF out of the box, the number of actual UI widgets and tools is rather limited. You might be surprised to see there’s no file open dialogs or any other standard dialogs. There’s no chart control of any kind, no graph, no bar plot or the likes. If you are looking for panels that automatically support touch based interaction with basic animations, you’ll find none. This lack of features is at the beginning quite disarming. You would expect to use additional UI libraries for advanced cases, but it feels like standard WPF controls don’t even cover the basic ones. Or they do so in such generic ways as to require a lot of work. The ItemsControl and its derivatives are examples of this uber-generality: any list of things fits the ItemsControl, be it an image gallery, a data grid, etc. This is great in a way, but it also means that the generic control does not exactly provide parameters to tune interactions for each specific case; when you want to customize the ItemsControl, you have to learn about the templating side of WPF. It’s a new way of extending a control, which is not based either on the familiar inheritance of a basic control type or on the composability of user controls. It’s not bad, it’s just yet another way of extending WPF.
Given the limited amount of controls, the other extension you might be interested in is to tweak the appearance or interaction of standard controls. For example, I needed to specify a different thumb for a slider control that was controlling the brightness of an image. Personally, I would have liked and expected a property on the control with a name like “ThumbIcon” or similar. Unfortunately, there’s nothing like that. What you need to do to make such simple tweak is to understand that WPF uses control templates to specify the visual appearance of any control (please note this a different type of template, not the data template used in the ItemsControl). This template can be extended, modified, or even completely replaced. In order to change the slider thumb as in my example, I had to update the control template. First of all, such control template is not immediately available in Visual Studio. After digging this template, I was confronted with a rather huge piece of XAML code that accounts for both vertical and horizontal sliders. Moreover, templates of built in controls are based on another WPF concept, the “parts and states” model. At the end of this experience, I was left with the feeling that writing my own slider from scratch would have been a lot easier. If you are creating simple controls that are used in well defined scenarios, consider whether you should really extend a built in control or rather write a more specific one from scratch.
Conclusion #3: you will not get a whole lot of controls with WPF. Be prepared to evaluate WPF control libraries, and be prepared to write at least some of the controls yourself.
Non linear-complexity decision paths
A last tricky point of WPF is that certain decisions might lead you in surprising dead ends. For example, you can create new controls either by composing controls, or by deriving from a basic control class. It seems like any of the two paths should be possible, with the second one possibly giving you more freedom to tweak the behavior of the control, whereas the first one is the easier route with more support from the visual editor. This might be true for a simple widget; if the control you are writing is a container control, the situation is different. Due to how WPF handles names, the difficult route is the one to take for containers or otherwise you won’t be able to use the container with named content. The fact is that it’s not straightforward to turn a composed control into a custom control; in the first case you have a XAML that specifies the concrete appearance of the control, in the second case you need to write a style, which is still XAML but with slightly different constraints. Turning a user control into a custom control is thus not just a matter of changing the base class name.
Conclusion #4: choosing the right starting point/class for using WPF might not be easy. Read the manuals before you start extending the wrong control.