Beachhead Dispatch

I have established a beachhead of sorts. A subset of the new model and UI is implemented. Everything is in place to launch the attack on conditionals. I have accumulated enough battle experience with C# and WPF to assess their strengths and weaknesses, which is the substance of this report. The bottom line is that WPF has some serious design defects, but as a package with C# it still looks like the best choice for my needs.

I am using C# in Visual Studio (Orcas beta) with the Resharper plugin as my development environment. Resharper adds to Visual Studio the crucial ability to interactively analyze your code as you edit, giving you deep semantic feedback. Visual Studio on its own is rather archaic, offering only type-based name completion (Intellisense) without interactive recompilation. Resharper’s interactive analysis goes beyond Eclipse or any other IDE I know of. It detects things like dead code, possible null references, instance methods that could be made static, unreferenced fields, un-updated writeable fields, etc. Resharper is sometimes a bit over-aggressive in its editing assistance, and there are sharp edges in its integration with VS. Eclipse is overall more polished and conservative. But VS plus Resharper is certainly a first class IDE. Unfortunately Rehsarper does not yet support C# 3 features yet, so I am foregoing them till it does. C# 2.0 is still more convenient than Java. The only real criticisms of C# I have are somewhat picayune: I hate the verbose XML doc-comments, and I really dislike the convention of capitalizing all methods and non-private field names. I inevitably end up with lots of fields spelled exactly the same as their type.

Here is a screenshot of the UI:

snap040707

I have been able to get WPF to do everything I need, but it has been frustrating at times, relying on trial and error and inspecting code samples. The documentation is incomplete and buggy. Worse, some aspects of WPF are so complex and irregular as to be practically undocumentable and hence unusable (more on that below). WPF reminds me of C++: too clever by half. As with C++, the response is to carve out a sane subset.

That said, the practical subset of WPF I am using is really quite a bit more powerful than any other UI framework I know of. It blows away Swing. That diagonal line in the screenshot is a good example. Old fashioned UI’s are based on rectangular decomposition of the bitmap, so anything that cross-cuts the containment tree goes against the grain. WPF allows arbitrary overlapping.

Flash is the closest competitor. WPF is more powerful than Flash, but considerably harder to use. I actually would have preferred the simplicity and ease of Flash. But Flash is limited to ActionScript, which in my opinion is still a toy programming language. Most of my code is not UI but complex data structures and algorithms that require a real programming language and a real IDE. How about collection classes? And refactoring? I’ll change my mind when I see a 50,000 line ActionScript app. Or when the ActionScript development tools are built in itself rather than Java. Come back and see me when you grow up, kid.

On to a specific critique of WPF. One of WPF’s claims to fame is that it is formulated not in terms of integer pixels but floating point physical dimensions (1.0 = 1/96 inch). This means the UI is resolution independent: if you run it on a screen with a higher DPI it does not shrink – it just gets sharper. Unfortunately there are some bugs/limitations in this. Resolution independence leads to antialiasing effects to represent partial pixels, which makes everything look blurry. So WPF supports “pixel snapping” to coerce integral pixel rendering for sharpness. But I have been unable to get pixel snapping to work in all cases. The simple case of a vertical line didn’t work – until I looked at the code generated by Microsoft’s WPF design app (Blend), which revealed an undocumented feature (Stretch=”Fill”) that fixed the problem. I have been unable to get pixel snapping to work properly between parents and children. For example the children of a Border will sometimes wipe it out when pixel snapping happens to round a certain way. The only solution I have found is to hard-code Border widths to be an integral number of physical pixels. To be fair, most of my measurements are still resolution-independent, which is better than using a pixel-based framework. I just find it disappointing to waste days tracking down magical incantations and workarounds.

Another strength of WPF is its font rendering. ClearType subpixel antialiasing is state of the art, and in my opinion is noticeably better than Apple’s. Though to be fair, Apple’s font rendering is biased to be faithful to high-res printing to meet the needs of print designers, while Microsoft has optimized for on-screen readability to meet the needs of app users. But ClearType breaks down in WPF in various common situations, leading to inconsistent font rendering in the UI. Specifically, popup windows don’t get ClearType. Unfortunately popups are ubiquitous, in comboboxes, context menus, and tooltips. I have heard conflicting explanations for this limitation. But it must be an architectural flaw in WPF, as the regular USER32 GDI system doesn’t have the same problem.

The biggest problems with WPF are due to its ambitious goals to make UI design more declarative and less code-centric. I applaud the intentions, but the results are decidedly mixed. One example of these problems is the styling and themeing system. UI controls have no hard-wired look and feel – it is completely specified in an XML dialect called XAML. This is extremely powerful and customizable. And unusable, because it is almost completely undocumented. For example, you can’t change the color of the border around a text box. Sure you can change the color – until the mouse travels over it, when it reverts to the themed color. There is no documented way to override that color. To do so, you have to completely re-implement the look and feel of the control from scratch with arcane XAML. You have to actually write a program just to dump out what the default XAML is in order to copy-and-paste an alternative. And even that depends on a ton of undocumented resources and behaviors to puzzle out. Thanks to Kevin Yancey for helping me out with this.

What a fiasco. A UI framework that ships with a set of controls whose behavior is undocumented and not incrementally customizable. And this was done all in the name of easier customization. Microsoft’s Blend design app solves this problem by providing a complete new set of “simple controls”, defined by 1100 lines of XAML which replace all the undocumented XAML of the standard controls. The Blend docs explain how all these styles work, and the set of global resources they depend upon, so you can customize them as needed. I have adopted Blend’s styles for my UI, so I am satisfied that I can do what I need. But the WPF team should be embarrassed by the necessity of this giant workaround.

I could say much more about XAML. I think it largely fails at its goal of being a declarative language for UI construction by non-programmers. It is just too complex and mysterious. But that is more a matter of my personal tastes and philosophy. I haven’t actually been using XAML in that way, so I don’t have first-hand evidence to back up my opinions.

To conclude, I want to emphasize that despite all my criticisms of the more ambitious aspects of WPF, I have found that a rational subset of it is, for my needs, the best UI framework currently available.

One Reply to “Beachhead Dispatch”

  1. Ah, you’ve finished just in time for the camera copy deadline 🙂 BTW, any idea yet what the two other Onward papers are?

    I remember back in the day when writing a Java UI library for Palm OS (way back in 1997. The UI library on PalmOS was pretty static, all widgets had to be layed out in database files that were synched on the Palm. I got around this by generating the database files on the fly on the Palm OS device 🙂

    Just goes to show UI library design is really close to language design.

Comments are closed.