My first WPF project – review
Juten Tach,
it’s almost done. After an intense weekend session, my colleague Hannes and i have almost finished our first WPF project (actually it’s not his first project, he had done some before). We still have got some little bugs to fix and some rough edges still need to be polished, but overall it’s done. Time to look back and write down some of our findings, especially from a flash developers point of view.
First, what have we actually done? I cannot talk about it in too much detail unfortunately, but in the end it is an application running on two notebooks, one being a tablet PC (the XT from Dell, hell i love this machine, i would buy one right away if i had about 1.500 Euro left for gadgets) and another being a crazy Dell XPS machine with lots of power to display big images and videos. The tablet PC is used as a touchscreen userinterface unit and the other one as a kind of “stage”, where the big images and videos are shown. They talk with each other over wireless LAN. The application utilizes a selfmade virtual desktop, that is bigger than the screen and can be dragged around to unveil different sections of the application. There are lots of “panels” floating around, that you can use and do stuff. This application is intended for showing content in a special “rich” way, so this is nothing you work with on a daily basis like your email program.
The first big thing was, we had a highly individual look and feel, so we were not able to simply take existing components (or “controls” as they are called in the windows world), we had to “skin” them (or to build individual “control templates” as you say in the .NET world) all. The learning curve for being able to choose the right way for doing so was quite high in my opinion. There are different concepts on what you can do to customize components. The easiest way is to apply a style to them, but this just gives you the possibility to change colors and change some properties of the existing structure of the standard component. If you want to have the complete individual look, then you have to use the before-mentioned templating approach. This one is very powerful, if you once understood the basic idea. You can completely build up your own component, still leaving it to be, say, a radio button. With that, you can build radion buttons, that have nothing in common with how radio buttons normally look like. For example, we have build an “accordion” style collapsable list view, where each item is actually a radio button, but we use them as little panels. Once we realized, how powerful this is, working with that philosophy was really becoming fun. I believe, Flex 4 is going into a very similar direction with their CSS approach and i think, this will be a huge success, because it opens very powerful ways of building individual components. We were really stunned how easy it was to leverage that concept and to build very individual components based on standard controls.
The next thing was to build a domain model for our application and to build the network connection. This was mostly done by Hannes, perhaps i can persuade him to write some details about his findings, but in general, once you have understood the basic idea, using WCF (yes, WCF, the package used for all kinds of communication issues in .NET) for communication really made things easy. But in general, we could never do something “on the go”, we always had to dig through books, documentation and forums until we found the solution. But in the end, building the domain model and the logic “under the hood” was more simple, because you more or less rely on the language and do not have to deal too much with .net.
A word about C#. I LOVE it !!! If you are coming from a Java and Actionscript background, it is very easy to dive into C#. C# doesn’t use packages, it has namespaces, which cannot directly be compared to packages, because they don’t have to be in sync with any folders. So you could theoretically have no folders but use lots of nested namespaces, which you shouldn’t do, however. C# has a lot of nifty little concepts to build little objects, that do not have to be full-blown classes but are typed nevertheless, like structs or enums. Also C# of course has Dictionaries like Actionscript, but typed ones, very nice. The coolest thing is for example, there is a struct Point, with x and y value. Since it is a struct, passing it around does not mean passing a reference, but rather a copy. Now, when you build a dictionary, which uses Point structs as its keys, you can map coordinates to … stuff, like in my case, event handlers. Sounds weird, but is so cool, i cannot think of any situation, where i should use a switch statement anymore.
Talking about Event handlers. This is soo complicated in .NET. At least if you want to have you own RoutedEvents, which can be compared to bubbling events in DisplayObjects in Flash. I cannot even say out of my mind, what you have to do, but there’s lots. In general, some things are way too complicated in .NET for my taste. The whole animation classes, for example. If you want to animate an object, then you could actually create a DoubleAnimation object, pass a duration, a “from” value, a “to” value and off you go. But then you cannot control the animation. For example, you cannot stop it. If you want to be able to stop an animation, you need to create a “StoryBoard”. So you build a StoryBoard, then you build your DoubleAnimation and then off you go. But if you want to have detailed control over the easing, you need to use “KeySplines”. So you build a “DoubleAnimtionUsingKeyframes” object, attach some KeyFrames with KeySplines to it, create a StoryBoard and pass the DoubleAnimtionUsingKeyframes to the StoryBoard and off you go. After a day or so i figured out what i had to use to create the desired effect. Of course, i’m exaggerating here. I know, that in my first days of flash, i had a hard time, too, understanding the details of how flash works, so i’m sure, this is normal.
And once you have the general idea, it is quite easy to work with it, since Visual Studio does a lot of work for you. We were using Visual Studio Express Edition and i have to say, this IDE ROCKS! The code completion is wonderful. Adding an event listener simply means pressing Tab twice, the first one for automatically adding the eventhandler assignment and the second one for adding the actual handler method. Very cool. Refactoring works like a charm and the debugging is also very comfortable, even though this is the free express edition, which only has a limited featureset, compared to the full studio version.
One big issue, we stumbled upon though, was rendering performance. As i said, we build a virtual desktop, that you can drag around, which means we are actually throwing everything around all the time. Animating complex controls has a hard impact on performance, since we didn’t find a way to temporarily tell WPF to not update the inner layouts of some controls while moving them around. And if it comes to bitmap effects, forget it. We actually wanted to add dropshadows to our panels, but no way. There were some things, we could do about performance, for example instead of using the Shape controls like Rectangle, Line and so on, we were drawing in a “DrawVisual” canvas, which means, that the result uses less cpu than the control version. Also, we drastically optimized the XAML, that Expression Blend produced, by using not so many grids and trying to use simple canvases instead of Stackpanels, Grids or other layouting controls. Expression Blend confused me more then it helped. Once you build your own individual controls, the preview in Blend sometimes does not show you a good preview, so it gets useless after some time. At the end, we were doing our controls mostly directly in XAML, which on one hand was slower, but produced more accurate and more optimized results.
Ok, enough said. All in all, i enjoyed working with WPF and C#. I’m sure, the next project would go a lot smoother. I hope, Microsoft will improve the rendering performance especially during animations and also the quality of font rendering, which sucks at the moment.
