Καλώς ορίσατε στο dotNETZone.gr - Σύνδεση | Εγγραφή | Βοήθεια

Everyday's Software Design

Scribbles on Software Engineering

Μάιος 2011 - Δημοσιεύσεις

Moving from WPF to Silverlight (part 2)

Trouble appears when it's least expected.

Continuing from part 1 let’s go into the things that not only will require more coding effort but will also change the whole design of your app. And if you are managing a team then it’s two times more difficult because you have to stand all their whimpering. Let the party begin:
  1. No default button! Long gone the simple WPF property on the Button class that was making it the default one for the page/form. What is even stranger though is that even in the web, typing in a textbox and then pressing Enter is the DEFAULT BEHAVIOUR!I mean why on earth someone wouldn’t provide this functionality on a web framework!
  2. No double click!Let’s say you have a grid for your search results. No you have to click (select) a row on the grid and then move the pointer to another button which will actually get your selection and do something with it! No more double click on a row and get things done.
  3. Focus on a control! So let’s say you move into a new screen and you want to focus on a textbox. It should be as simple as a method call right? m_myTextbox.Focus(). Weeeeeeell, this is probably not going to work!!! Yeah, you see it will work fine on a OOB application but on a browser app you need first to focus on the Silverlight plugin and then focus on your control! So you actually need something like:
    System.Windows.Browser.HtmlPage.Plugin.Focus();
          
    RegularTextBox.Focus();
    Or if it’s that you want to focus something on startup or on Loaded event then you have to call:
               Dispatcher.BeginInvoke(() => input3.Focus());
    Unbelievable right??
  4. No keyboard typing selection in ListBoxes/ComboBoxes! This is another one that makes users’ nerves go high. Usually on both a desktop and a web app when there is a ComboBox on a screen you can start typing something and the ComboBox selects the item which has a text that matches the typed characters. There is no such thing in SL. The only acceptable solution I managed to find is to code a behavior that would select an item but only on the first typed letter. So if a user types three letters fast my behavior will execute three times selecting a different item each time.
  5. Asynchronous world! This is the most serious one and that’s why I left it last. Probably most of you WindowsForms/WPF application designers have thought about pressing a next button, make some operations secretly from the user on another thread and then when that thread comes back actually present the next page. Well I have news for you! It’s not that easy anymore! Since every call to a delegate/callback/web-service/Agatha-rrsl method is ASYNCRHONOUS! What this means is that if you want to calculate something before going to the next screen and you want that calculation to be done on the server side then you have to somehow transform this call into a synchronous one as there is no way it can be inherently synchronous (there are a few very nice solutions out there, but I won’t get into the details). Just think of it for a moment. We are taking about some serious changes here, especially if you have a SOA with any kind of Service bus/WCF/asmx/Queue services talking to each other.
Most of the problems I described in these two posts can be solved with various workarounds. But the point is that most of these things should just work. We are talking about behaviours that are considered DEFAULT for a long time now and users are expecting them from your app.

All in all, I still remember the words of my old colleague about “how easy it should be” and seriously I am laughing! If it’s not a business critical requirement DON’T TRY IT! Just don’t!!! Think about it from the very beginning of the project and make sure you understand your domain and business requirements and of course never listen to an optimistic colleague! ;) 
Moving from WPF to Silverlight (part 1)

Never believe it is as easy as they say...

I used to have a colleague in the team I manage that was sure that moving back and forth from WPF to Silverlight was easy!!! I will dedicate these series to him as reality proves us most of the times wrong. (Research is the only path to knowledge).

So I am the architect of a quite big project and it was originally coded in WPF. But since we wanted to move to a unified architecture where both our users and the clients will have the same user-experience, we decided to move on to Silverlight. There are tons of things that are different and some of them are addressed to Silverlight 5 but still, there is quite a distance.

First things first… When you just copy over the code you will see you xaml getting full of red lines. The exactly same controls are not on the same namespace!!! (WTF?). So let’s say you have a label, well your xaml tag is no more <Label>  but instead it should be <sdk:Label>.

Then I moved on to test my colors and text fonts. Again we had to change most of our resources for the text to render correctly. But the best part is the Reflection capabilities. It was well known that SL will have a minimized API version of .Net and I was prepared that our reflection helper class would have problems. What I did not expect though was that BindingEngine would complain when I was trying to bind on protected properties or even public properties on internal classes! To make myself clear:
We are quite serious about coding standards and framework guidelines in my team so we make all of our classes internal until we need to "open" them. So let’s say we had a page call MyFirstPage and the code-behind file was starting like that:

internal partial class MyFirstPage
{
//...
}

and the xaml code was like that:
<UserControl
         x:Class="MyNamespace.MyFirstPage"
         x:ClassModifier="internal">
//…
</UserControl>

Well in this situation any binding will fail with the message that the BindingEngine could not find the property named “blah” as the reflection mechanism used is unable to resolve internal classes!!! I was seriously disappointed. I mean it's the same class after all! It shouldn’t matter whatever the access modifier is.

Next incompatibility was the fact that we could no longer have multiple windows. I know this is now possible in Silverlight 5 Beta (which I am currently testing) but at that point in time we had to make some serious thinking about how we are going to be user friendly and still present the same amount of information to the user. The problem with child windows - as you may know - is that they don’t let you interact with the background window (the “parent”) and so you are left with one working window at a time.

I won’t talk about MVVM concepts that were not fully supported as I decided to let my team go away from that MVVM buzz-pain-in-the-ass. I have yet to see a real complex business MVVM application (working for portfolio/transaction management in banks or insurance companies).

I will talk though about how frustrating it is to not be able to chrome your OOB (out-of-browser) window any way you like. Well we have managed some pretty neat stuff with our own but it took us a lot of time and effort. And as if these were not enough already, autoupdate needs you to have your code signed for having an elevated trust OOB getting the new version. Moreover, if you dare update the Silverlight version you build against the auto update will fail anyway. And of course you have no control over the whole operation. You just have one method call (to check and download the update, yeah two in one either you want it or not) and an event (just to let you notify the user that the next time he starts the app it will be the new version). That’s it. Period! I really miss ClickOnce

In part 2 of this post I focus on the design changes that one has to make as Silverlight lives in an asynchronous world, has no double clicks, no default buttons and last but not least the focus operation is not as trivial as it used to be.