I've blogged previously about inconsistencies between SL 2 Beta 1 and WPF. In my previous post I mentioned a few critical things that I felt would make it hard for WPF developers to move code between the two platforms. Most of my complaints were not addressed in the updated Beta 2 of Silverlight, but I didn't expect them to be. Some issues were just too complicated to try and fix that quickly.
The purpose of this post is to mention a few more things I have found. This list of "issues" comes directly as a result of my work in creating a common code base for Caliburn, for both the WPF and Silverlight platforms. While many of these issues will be felt more painfully by developers trying to migrate their skills from WPF to Silverlight, most of them will also affect developers with no previous experience in this area. Some of these problems are obscure. In those cases, I will try and give some explanation of why it is important and how if affects the bigger picture of developing RIA's with Silverlight.
- DepencencyObject, UIElement, and FrameworkElement all have internal constructors.
For some reason (probably due to Silverlight's unmanaged goop) none of these fundamental base classes can be extended through inheritance. They all have internal constructors. The problem with this is, often times a developer has a need for a simple object with dependency properties. In WPF I would just inherit from DependencyObject but in Silverlight the lowest level base class I can inherit from is Control. But, I don't want a control! This limitation also means that it's impossible to create lightweight UI components.
- No Visual base class.
- No Freezable base class.
These base classes are not directly worked with by WPF developers most of the time. But, their affects are felt nearly all the time. Visual, for example, is the base class that represents all renderable elements in WPF. This plays an important role in everything. They've gotten around this in Silverlight mostly by merging its functionality into other base classes. Two areas related to Visual that represent functionality missing from Silverlight are printing and rendering to bitmap. Freezable is an interesting class because it allows non-FrameworkElements to hook into the logical tree. Thus things like transforms and brushes can be databound in WPF, but not in Silverlight. The absence of Freezable and to a greater degree the absence of a logical tree has the most limiting and far reaching negative affect on Silverlight. This is also the source of Silverlight's stunted databinding features, including the lack of ElementName binding.
- IsEnabled does not exist on UIElement.
This feature alone is enough to make it very difficult to build any real world business application with Silverlight. Of course there are workarounds, but that would be painful. The issue is that you cannot disable any part of the UI in Silverlight like you can in WPF. With WPF, all UIElement descendants can be disabled; this includes panels, text boxes, buttons, etc. With Silverlight the property exists only on certain classes (ContentControl, Slider and Thumb of all things). This means I cannot disable things like TextBox and ListBox and I cannot disable an entire panel of controls.
- FrameworkElement is missing the IsInitialized property.
- FrameworkElement does not have an IsLoaded property.
- FrameworkElement is missing the Unloaded event.
The absence of these properties is not that big of a deal to me. But, I'm used to them being there, and taking that for granted I was robbed of several possible "simple" solutions to some of the problems I was trying to solve. Of most importance is the Unloaded event. In combination with Loaded it enables developers to write specific code that responds to the addition and removal of an element from the visual tree.
By itself this isn't major. Indeed, at present, there aren't many things in Silverlight that could derive from Selector. Mainly ListBox, but if they ever add a ComboBox (I can't believe this control is missing...) it should derive as well. The overarching theme here is that the entire class hierarchy greatly differs between WPF and Silverlight. No Visual, Freezable, or Selector. Base classes can't be inherited (due to internal constructors) and important properties are missing. As long as you stick to simple applications, this is fine. But the minute you try some form of generic programming, often necessary in real applications....BOOM!
- Exception (and its derivatives) have non-visible serialization constructors.
Again, not a major deal. Just know that if you are used to providing serialization constructors for custom exceptions, you won't be able to in Silverlight. The serialization constructor of the base class is internal and there is no binary serialization in Silverlight either (which is perhaps the bigger issue).
- DependencyProperty does not allow a way to declare metadata for a property.
Normally in WPF you can declare more information about a dependency property, but Silverlight does not allow this. Some examples are the default binding mode and whether or not a property affects layout or rendering. I'm guessing that somewhere under the covers Silverlight is making some serious assumptions.
- There is no LogicalTreeHelper and more importantly, no logical tree.
- No name scopes.
Though many WPF developers may not deal directly with these two pieces. Their presence governs so much of the way that WPF behaves at runtime. Not having these seemingly fundamental pieces has caused copious hair pulling and screaming. This is also related to the absence of Freezable. (Frankly, I'm still not sure how Silverlight works at all without these pieces.)
- No custom markup extensions.
Annoying! I always use custom extensions and it is exceedingly important if you want to build any type of framework on top of Silverlight that eases common tasks. Why are the existing markup extensions hard coded?
- Some of the assembly names are different between .NET and Silverlight.
This is not a big deal, and I attribute it more to WPF's poor assembly naming convention, because Silverlight actually does it more the ".NET way." You'll need to know about this if you do multi-targeting though.
- There are differences in the runtime behavior of the dynamic method API.
Again, not a big deal. But, it's confusing when there are public methods that you can call that will always throw an exception at runtime. Pay attention to the words SECURITY CRITICAL in the intellisense. If you see this, don't bother.
- You cannot represent a class in Silverlight Xaml with a Name property.
Weird. Ok, to see what I'm talking about, follow these steps:
1. Create a new Silverlight project.
2. Add the following class definition to the project:
3. Change the markup for Page.xaml to match the following (make sure the namespaces match your project):
4. Make sure you add the event handler for the button to the code behind.
5. Set a break point in the click handler.
6. Run the application and click the button. Using the debugger, drill into the Content property of the Button and examine the Name property. You'll see that the Name property is null even though you set it.
- Binding is severely lacking.
Let's just face it. Silverlight data binding shouldn't even be compared to WPF databinding. Silverlight's version is so stunted that it's embarrassing. There's no element name binding, for starters. This is one of the most important features in WPF data binding.
In conclusion, I'd like to reiterate that I actually like Silverlight. It has a lot of potential. I just wish more attention would be given to the foundations. If you get the core right, I can do anything. Otherwise I'm limited to what Microsoft can imagine in their highly rushed dev cycle.
07-26-2008 6:58 PM