Quite a while ago, Microsoft has released Silverlight. The “little brother” of WPF. As loyal reader of my blog, you might already know that I am a big fan of WPF. I like it so much, that I even wrote my own MVVM Framework and more (also called Catel). From January 1st, I will stop at my current client where I developed a large application for a radiation hospital. With the application, the complete patient dossier can be digitalized. The most important techniques used are WPF and WF (v3.5). Anyway, since I am out of work, I wanted to focus on some more techniques than WPF only, and what better way then to port Catel to Silverlight.
The library of Catel was completely build with WPF in mind, but since Silverlight is the little brother, it shouldn’t be hard to port the software, right? Oh boy, what was I wrong! This blog is to give you an insight of the Catel kitchen where the Silverlight version of Catel is being developed.
To give a bit of background information, Catel exists of 2 major assemblies:
- Catel.Core => core library that can be used in Windows Forms, ASP.NET, WPF
- Catel.Windows => wpf specific library containing an MVVM framework and WPF controls
So, I decided to port Catel.Core first. It contains no UI, so shouldn’t be too hard, right? As a complete noob, I started a new Silverlight library project, and first thing I did (or at least tried) was to link to the log4net library. Mistake #1: you cannot link to “normal” .NET Framework assemblies. Say what?! Yes, you read it right: even though Silverlight is “part” of the .NET Framework, you can only use Silverlight libraries as references.
Ok, shit happens, it’s the little brother, so it doesn’t have to be as mature as WPF. In the new Silverlight library, I started linking all the files of Catel.Core so I have 1 actual source file. However, what happened: compile errors because the Serializable attribute is unknown? Oh my, what hell did I go into? But, since I just started porting, I decided to continue the chosen path, so I nicely wrapped all the binary serialization code into #if !SILVERLIGHT codeblocks.
I am also very interested in changing properties. Sometimes, I want to make sure I clean up an old value before it is changed. The INotifyPropertyChanging is a very nice interface that fits exactly for this requirement. Of course, in Silverlight, this interface is not available. Therefore, I always need to keep track of both the previous and current values to make sure that library behaves exactly the same in WPF and Silverlight.
Another nice “feature” is that Microsoft decided to completely drop support for XmlElement and XmlDocument. I now have to use the XElement and XDocument classes. Luckily, I wrote tons of unit tests, so converting the existing code to the new LINQ-to-XML wasn’t too dangerous.
Up to the next challenge. I want to use some tracing and timing. This is part of the Catel Framework. But, what happens? The class Stopwatch does not exist in WPF? Do I really have to write my own implementation? Ok, let’s do that, I don’t want to give up yet...
Now we have fought our way through the easy part of the library, let’s continue our path to the UI library. One of the things I like to do in WPF is to be able to get a binding of a dependency property. But, what seems, BindingOperations.GetBinding does not exist. Apparently, they found it useful to allow developers only to set bindings. Luckily, there is a workaround to use GetBindingExpression() on the control that defines the dependency property, and then use the ParentBinding property to retrieve the actual binding.
Sometimes, you just want to search for a control inside the logical tree of an element. So, let’s use the LogicalTreeHelper. The what?! Oh, it isn’t available in Silverlight. Do I really have to write my own version of the LogicalTreeHelper? Yes, but no problem, I was fixed within the hour (at least, for the part I needed such as FindLocigalNode).
Now let’s import the very useful converters that I wrote for Catel. Again, lots of compile errors. It seems that the ValueConversion attribute isn’t available in Silverlight either. Ok, I will wrap the attributes with the #if !SILVERLIGHT codeblocks again. The cool thing is that I have to write Silverlight so many times, that I am currently a master in typing Silverlight without any spelling mistakes extremely fast!
Just when I thought it couldn’t get any worse, I found out that custom RoutedEvents are not supported either. Nice, the big plus of WPF is gone here too.
But hey, we don’t give up so easy, are we? No, of course not. According to all the tweets, Silverlight is “great”, “awesome”, etc. Still haven’t found out why, but maybe I am just too stupid to see the point (BTW: that was sarcasm).
The last point I will make in this article is that the basic implementation of the UserControl is just too minimal. There is no IsLoaded property (but there is an event, do I really have to define my own properties for this?). Also, the DataContextChanged event is missing. But for this, a workaround is available so I don’t want that to bother me too much. What does bother me much is that the UserControl does not implement INotifyPropertyChanged, nor does it have a virtual method called OnPropertyChanged. In other words: I can’t even handle changes of properties in the user control!
The conclusion is that Silverlight is not the little brother of WPF, it’s the unborn grandchild! Of course, I won’t surrender so easily so I will continue to battle the restrictions of Silverlight. However, I hope this gives people that read this blog post an idea about the most basic differences between Silverlight and WPF, and why people should definitely choose WPF if they want to build a real business application.
Summary of all issues I walked into (until now)
- You cannot link to “normal” .NET Framework assemblies
- Binary serialization not available
- No INotifyPropertyChanging
- No XmlElement and XmlDocument
- No Stopwatch class
- No BindingOperations.GetBinding
- No LogicalTreeHelper
- No ValueConversion attribute
- No custom RoutedEvents
- UserControl lacks of functionality