Delay's Blog is the blog of David Anson, a Microsoft developer who works with C#, XAML, HTML, and Azure.
In the Silverlight 2 ListBox/ScrollViewer FAQ, I mentioned that I'd done a lot of Silverlight control development on WPF. I spoke with a number of people at MIX08 last week and many of you wanted to know more. So I've created a Visual Studio solution with one project to compile these Silverlight controls on WPF and another project to run the corresponding unit tests. I've also implemented a simple demonstration of the WPF ListBox/ScrollViewer running side-by-side with the Silverlight ListBox/ScrollViewer (all on WPF):
While there are some obvious style differences between the default look and feel of the two platforms, the control functionality is very similar. To prove it, I've attached a ZIP of the solution to this blog post so you can run the demo application on your own machine. [Aside: I did not say the behavior was identical, just very similar. :) ]
And though I didn't enable code coverage by default, those of you with the Visual Studio Code Coverage feature installed can easily turn it on by editing the LocalTestRun.testrunconfig settings. When compiled for WPF, ListBox and ScrollViewer live in the WPF namespace to avoid colliding with WPF's classes in System.Windows.Controls. So we can see below that the overall coverage for these controls is a smidge under 80% (the uncovered code is mostly involved with user interface manipulation (ex: mouse and key input) which I wasn't able to flush out because I ran out of time):
So if you were wondering whether it was possible to easily share code, XAML, and unit tests across both Silverlight and WPF, the answer is a definite YES! :)
What's the meaning of the WPF/WPFIMPLEMENTATION defines in the controls source code? The development of ListBox (+ListBoxItem) and ScrollViewer (+ScrollContentPresenter) was done in parallel with the development of their base types (e.g., ItemsControl, ContentControl) and also in parallel with the development of the Silverlight 2 platform itself. To minimize the risk/impact of developing on a changing foundation, I did much of my development and unit testing on WPF by deriving from the corresponding base classes, using only the subset of WPF that Silverlight exposes, and avoiding features specific to either platform as much as possible.
When compiling and running on WPF, I would add "WPF" to the list of conditional compilation symbols for the project. Therefore, code inside an #if WPF block applies only when running on WPF. In many cases, the pattern is #if WPF ... #else ... #endif and this corresponds to instances where some bit of code needed to be different between the two platforms (typically because it used features that weren't identical across both). In some cases, the relevant code only applies to one platform and the #else is missing or #if !WPF is used instead.
#if WPF ... #else ... #endif
The meaning of "WPFIMPLEMENTATION" is similar and is used by the unit tests for code that applies only when testing the WPF implementations of ListBox or ScrollViewer. I used unit tests in three different scenarios to help ensure the code was as correct and compatible as possible: testing the Silverlight implementation on Silverlight, testing the Silverlight implementation on WPF (#if WPF), and testing the WPF implementation on WPF (#if WPF, #if WPFIMPLEMENTATION). Though it may seem silly at first, the point of testing the WPF implementation on WPF was to make sure the unit tests were validating the correct behavior.
#if WPF, #if WPFIMPLEMENTATION