Category: Silverlight

WP7: Toolkit Fed 2011 Release

Silverlight Toolkit

Head over to codeplex to grab the just released Fed 2011 Silverlight For Windows Phone Toolkit.

In this version the toolkit brings you default tilt effect on most common controls and also included the PerformanceProgressBar by Jeff Wilcox.

Definately not something huge but why not just grab it and recompile your project while it’s completely free?

Update: I’ve also noticed that page transition animations are now using better easing functions then the previous version.

Advertisements

RX: A reactive approach to event handling

Microsoft released RX (Reactive Extensions) for .NET on November 2009, but I bet there are only 1% of the developers are really using it so far. Apart from that Microsoft is not really pushing it, the real reason, IMO, could be both that it is only suitable for some very specific development cases, and the idea it is using is quite hard to get around with from scratch. Because it is using a reversed logic to process objects.

Let’s put it simple:

  1. RX is the library to support Reactive Programming.
  2. Reactive Programming means your code “react” to something when it becomes available instead of “act” on it actively. So it’s more of a passive approach.
  3. RX aims to convert objects that you want to interact into a list, and invoke an action each time an item is added to this list. The idea is similar to listening to an ObservableCollection.

Why do I reckon RX is only suitable for some very specific cases? Let’s take a look at this very simple example:

Simple example: Processing a list

Let’s say we have a list, filled with objects, and we only want to print out the string objects in this list:

List list = new List<object>() { "string 1", 1, "string 2", 2 };

What we normally do is to use a loop to process this list:

foreach(object obj in list) if (obj is string) Console.Write(obj.ToString());

In the normal way, we actively go through each object in the list and process it. The RX model takes this in a passive way, asynchronously:

list.ToObservable().Where(obj => obj is string).Subscribe(obj => Console.Write(obj.ToString()));

In the RX model, you convert the normal list to a list that can be observed by calling list.ToObservable(). This will return you an IObservable<object> which is a RX supported list and able to use all of the magical RX functions and extensions. The Where functions takes a function delegate that determines what object in the list will be selected, and returns the filtered list. The Subscribe function can take an Action<object>, which will be called against each object in the list as soon as they become available. In our case, because the list is pre-filled, so the objects are already available. When you execute the Subscribe function, it performs similar to our for loop, processing each of the already-available objects in the list.The real difference here is that:

  1. The monitoring and processing happens asynchronously
  2. If you add more items to the list after the RX statement, the newly added items will also be processed as soon as they are added. Because you have “subscribed” to the list and are monitoring it.

This could be useful when you are not sure when items will be added to the list, if you don’t really want to use an ObservableCollection. However, RX runs slower than the traditional model and requires more memory, as it is doing a whole bunch of conversion and event handling behind the scene.So far, RX has been mainly used in Silverlight, where user interaction with the UI can become quite complicated and asynchronous processing is the only option in most cases.Let us walk through the following example to understand why RX could be critical to a rich user interface.

Real life example: Detecting mouse button press and hold event

Take a minute and think about how you would implement the detection of a mouse button press and hold event in Silverlight, let’s say, we want to do something when the mouse left button is down for 2 seconds without moving?

The triditional model

You definitely need a timer to time this 2 second interval:

DispatcherTimer myTimer = new DispatcherTimer() { Interval = TimeSpan.FromSseconds(2) };
myTimer.Tick += (s, e) =>{
    // Do something when the timer ticks.
};

To start the timer, we will need to listen to the MouseLeftButtonDown event:

this.MouseLeftButtonDown += (s, e) =>
{
    myTimer.Start();
}

We also need to detect mouse up and mouse movement in order to cancel the timer, so that the timer tick event doesn’t miss fire when the user doesn’t really mean to hold down the mouse button:

this.MouseLeftButtonUp += (s, e) =>
{
    myTimer.Stop();
}
this.MouseMove += (s, e) =>
{
    myTimer.Stop();
}

This could be all if you are working on a normal Silverlight app, but it gets messier for a WP7 app where multi-touch needs to be considered. You want to cancel the timer as well when a second finger is pressed on the screen.To do this, you need to modify the MouseLeftButtonDown event handler above:

this.MouseLeftButtonDown += (s, e) =>
{
    myTimer.Start();
    // Register a 2nd event handler to detect 2nd finger press.
    this.MouseLeftButtonDown += SecondMouseDown;
    // Because we are attaching a new handler each time the mouse left button is down,
    // it is important to detach this event handler when it is invoked,
    // so that the same handler doesn't get invoked multiple times.
}

public void SecondMouseDown(object sender, MouseButtonEventArgs e)
{
    // Detach this event handler to prevent been invoked multiple times.
    this.MouseLeftButtonDown -= SecondMouseDown;
    myTimer.Stop();
}

This traditional event handling model works fine, except that it requires creating a timer plus 4 event handlers, and code is scattered making reading and maintenance difficult.

The RX model

I’m gonna give you the complete working RX code to do this, then explain through it:

public partial class MainPage : PhoneApplicationPage{
    // Constructor
    public MainPage()
    {
        InitializeComponent();
        Observable.Throttle(Observable.FromEvent(this, "MouseLeftButtonDown"), TimeSpan.FromSeconds(2))
                      .TakeUntil(Observable.FromEvent(this, "MouseLeftButtonUp"))
                      .TakeUntil(Observable.FromEvent(this, "MouseMove"))
                      .ObserveOnDispatcher()
                      .Subscribe(e =>
                      {
                          // Do something here...
                      });
    }
}

This is it! 1 single RX statement with no event listener at all.First, we use the Throttle extension to specify that, whatever we are monitoring, we don’t care for an initial period of time. This extension takes 2 parameters, the first parameter tells the extension what observable list to monitor, and the 2nd parameter says how long the initial period is.Then we specify with the 2 TakeUntil, that we want to stop monitoring by MouseLeftButtonUp or MouseMove event.We also need to use the ObserveOnDispatcher extension to specify that when we perform any actions on the list, perform it on the current thread (i.e. the UI thread). This can prevent any invalid cross thread access exceptions been thrown.Next we use the Subscribe function to start monitoring this list. When the MouseLeftButtonDown event happens, and after the initial 2 seconds period, execute the Action we specified for the Subscribe extension.

WP7: Activating before Deactivated, a problem of Tombstoning

Tombstoning is the process that you save your app’s “state” to, usually Isolated Storage when the user leaves the app, so that your app can reload the state when it is been reactivated via the Back button.

Before going into the problem, you should have a good understanding on this concept. Shawn Wildermuth has a very good walk through of tombstoning and James Ashley also talked about why deactivating the application is not the same as tombstoning.

Assuming you save your app state using the Application_Deactivated event handler, there should be no problem at all, except this boundary case: what if the app is re-activated even before the Application_Deactivated handler finishes it’s execution?

It’s quite simple to produce this situation. You can:

  • either put a break point in debug mode in the Application_Deactivated event handler, then press Home then Back buttons, then F5 your app to resume it;
  • or simply put Thread.Sleep(5000) in the event handler and press Home then Back buttons within 5 seconds.

If you observe this process carefully in debug mode, the behavior is quite interesting here: the Application_Activated event handler will still be invoked after Application_Deactivated but your app instance is not destroyed and recreated. This means when the app is reactivated, none of the constructor of your objects will be called, as if there weren’t a deactivation at all. To put this in short: tombstoning is not needed in this case!

Having this in mind, we should carefully code our logic so that we don’t do unnecessary tombstoning operations that may cause unwanted side effects.

For example, if you were saving and loading your setting like this:

private ObservableCollection<string> _searchResults;
public ObservableCollection<string> SearchResults{
    get { return _searchResults; }
    set { _searchResults = value; RaisePropertyChanged("SearchResults"); }
}

private void Application_Activated(object sender, ActivatedEventArgs e)
{
    SearchResults = LoadSearchResultsFromIsoStore();
}

private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
    SaveSearchResultsToIsoStore(SearchResults);
}

The above code could trigger an unnecessary write and read of IsolatedStorage in our special case, and if SearchResults is large and bound to a UI list with complicated item template, there will be much more side effects then just performance hit for reloading it unnecessarily.

Unfortunately, it’s most likely that we won’t be able to avoid the potential redundant write to IsolatedStorage in Application_Deactivated, because there is no way that we can predict if the app will be reactivated too soon. But we can always be smart in Application_Activated. For example:

private void Application_Activated(object sender, ActivatedEventArgs e)
{
    if (SearchResults == null) SearchResults = LoadSearchResultsFromIsoStore();
}

In this example, we can easily know that if the app has been destroyed or not by checking whether SearchResults is null. If the app instance was never recreated, then SearchResults would still be pointing to something other than null. Depends on how you organise your tombstoning logic, there could be a thousand different ways to be smart here. Just keep this case in mind when you code.

WP7: Everything About ListBox Performance

If you found this blog post, I bet you’ve already had a hard time dealing with the unsatisfactory performance of the Silverlight framework of WP7. Let’s face it, managed code has no chance against native code (read: objective-c) when coming to execution performance. And one of the most frustrating part of WP7’s performance issue could be scrolling a ListBox-like control.

Boldly speaking, ListBox-like control is the most critical control for a WP7 Silverlight app. For any kind of average complex WP7 app, you’ll have to use a scrollable list in one or more of your screens.

Stack Panel

The golden rule here is that the simpler the UI is, the faster the performance can be. So if you list is small and static enough, like less than 30 items not using an ObservableCollection, you may try putting a StackPanel in a ScrollViewer and have the items in the StackPanel generated in code.

Items Control

If what you need is just a list that binds to a collection and executes some code or navigates to another screen when you pressed on one of its items, you could consider re-implementing your ListBox using the ItemsControl.

The standard ListBox extends the Selector class which further extends ItemsControl.

ListBox Inheriting Structure

The ItemsControl class has all of the important ListBox properties such as ItemsSource and ItemTemplate. What it is lacking is the ability to “select” an item and it doesn’t scroll by itself. Therefore, you may implement your list in the following way:

<ScrollViewer VerticalScrollBarVisibility="Visible">
    <ItemsControl ItemsSource="{Binding MyDataCollection}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <HyperlinkButton NavigateUri="/TargetPage.xaml" Click="DoSomeThing">
                    <HyperlinkButton.Template>
                        <ControlTemplate x:Key="SimpleHyperlinkButton" TargetType="HyperlinkButton">
                            <ContentPresenter Content="{TemplateBinding Content}"/>
                        </ControlTemplate>
                    </HyperlinkButton.Template>
                    <!-- Your control template here -->
                </HyperlinkButton>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</ScrollViewer>

As you can see, you can bind collection to the ItemsControl‘s ItemsSource property just like a ListBox. The use of the HyperlinkButton lets you directly set the URI of the new page that you want to navigate to, saves from writing event handler in the code behind. Or you can also use the Click event to do extra processing in code. Note that overwriting the HyperlinkButton‘s Template is compulsory as the default template is only capable of displaying string value. You may also use a Button instead of a HyperlinkButton, and the template overwriting is still recommended as it simplifies the layout of the Button control, if you don’t need the extra border and pressed/disabled effect of the Button control.

The ItemsControl does not virtualise UI elements in the list. This can have a memory impact if your list is large. If you are not planning using the LongListSelector (see later) in this case, I would recommend, if applicable, loading a limited number of items at load time and give the users a button at the end of the list to load more items:

Load Button At End of List

Deferred Load List Box

David Anson blogged about loading items in the ListBox with his DeferredLoadListBox. This is also a ListBox that uses StackPanel but delay creates the UI. The catch with DeferredLoadListBox is that it only defers the load. Once the UI elements are created, it does not virtualise them either. In fact, during my testing on a Samsung OMNIA 7, the over all scrolling performance of DeferredLoadListBox is even worse than the standard ListBox.

Long List Selector

The LongListSelector shipped in the SilverlightToolkit for WP7 is, in my opinion, the ideal control for loading large number of items when binding to a data collection. This control virtualise the UI items in the list to keep it’s memory footprint small. To put it simple, it destroys the UI elements when they are off the screen and recreates them when they are back in. You can set the BufferSize property to specify how many page’s items that you want to keep in memory. The default value is 1 page so UI items are (supposed to) destroyed immediately when they are out, you may test increasing this value to suit your app. Another interesting property is MaximumFlickVelocity. Decreasing this number can slow down the inertial scroll speed and buy some more time for the list to load it’s items. The default value is 4000. You may find 2500 a good number to start with if you need to tweak this.

It is also important to know that binding a collection that implements the IList interface (such as ObservableCollection) is much faster and resource friendly than those don’t, this is because you can also virtualise data using such a collection. Take a look at this page for more about UI and data virtualisation.

Pay very much attention to the Loaded event of items in your list especially when using the LongListSelector. This event is raised every time when an item is re-created. Which means handler of this event may get executed multiple times as you scroll the list. I would suggest keep away from the Loaded event of the items. If you really need to execute something on each load, consider doing it in a background thread. I have previously talked about this technique and limitation about it.

Lazy List Box

Last but not least, Peter Torr has implemented a very unique way to improve scrolling performance via his LazyListBox. His basic principle is “Don’t do work while the user is scrolling“. If you don’t want to read through his thoroughly explained blog, you can just download his sample code and copy out the LazyListBox class and start using it like a normal ListBox. The only change here would be, when you create the ItemTemplate for LazyListBox, you create a simpler (preferably no image) item for preview purpose. Because LazyListBox will show items using this template while it is scrolling. The real template is LoadedItemTemplate. LazyListBox will reload items in the current visible area with this template as soon as scrolling is stopped. Similar to LongListSelector, LazyListBox also virtualises off screen UI elements. However, you can optionally store some UI elements using the CachedItemTemplate to avoid heavy reloading activities. I suggest have a good read of his blog post if you really want to take LazyListBox as your solution.

What more to expect

After all, before Microsoft releases updates to improve the performance of the Silverlight run-time of WP7, there’s limited amount of optimisation that we can do.

When the WP7 developer tools first shipped Microsoft Silverlight Developer Jeff Wilcox tweeted invaluable performance tips for 3 straight hours. Tim Heuer collected Jeff’s tidbits and posted those on his blog.

While the list is fairly long, I’ve picked some obvious ones that are usually ignored by developers:

  • Pivot starts up faster than Panorama.
  • Always use JPEG over PNG if you can.
  • Set the compile option of image and media files as “Content” instead of “Resource” (in the property window).
  • Avoid using images larger than 2000 x 2000 pixels, not even the background of your Panorama.
  • The simpler your layout is, the faster the performance.

WP7: Limitation of Multi-Threaded UI Operations

Loek Ouweland has recently blogged about more responsive UI operations utilising the BackgroundWorker class. To put it simple: if you execute your code on the same thread as the UI, then the UI won’t be updated/re-drawn until the execution is finished. This is actually not a new problem to WP7, it’s a common behavior of almost all platforms out there.

The example in Loek’s post is a for loop that generates many star patterns on the UI. During the generation process, Loek wanted to show the progress of the generation using a progress bar. The progress bar would never change during the for loop because the loop happens on the same UI thread, which prevents the UI from being updated until all of the stars are added to the UI. The solution was to use a BackgroundWorker to perform the loop and in each loop use the Dispatcher object of the UI thread to add the star to the UI.

While this seemed to be working just fine, there’s an obvious limitation in this approach, that all UI element related operations still need to happen on the UI thread.

Let’s take Loek’s example again. The reason why Dispatcher is used in the BackgroundWorker solution is that you can’t directly access objects on the UI thread from another thread.

Usually, where you really want to use this technique is when you have a large amount of complex UI elements that you need to generate using a loop in the code behind. The limitation of this approach is, that you are neither able to access the UI layer nor able to generate any UI elements in the background thread and pass them to the UI thread. As soon as you try to create any object that inherits the DependencyObject class in the background thread, you’ll get the same Invalid cross-thread access exception.

Which means, you may give your UI a chance to update itself between the moment of jumping to the next loop, but you may still experience UI freeze up while you use Dispatcher to generate that complex UI element inside each loop, depends on how complex the UI element is.

Silverlight: Unhandled Exception and MVVM Light

The MVVM Light Toolkit is one of the most popular MVVM framework that Silverlight developers are using. While it’s very handy for data binding and manipulation, you have to beware that there’s a little difference to handle unhandled exceptions.

Usually you would expect all unhandled exceptions would end up in the automatically generated Application_UnhandledException event handler in yoru App.xaml.cs file. A lot of developers would create their custom exception class and catch all exceptions in this event handler as a centralized place to process the exceptions and perform appropriate actions accordingly. But, when you try to raise an exception in, say, a property in one of your MVVM Light view model, this may not always be the case.

For example, in my main view model, I have a simple property:

private int _price;
public int Price
{
    get { return _price; }
    set
    {
        if (value < 0) throw new MyException("Price cannot be less than 0.");
        _price = value;
        RaisePropertyChanged("Price");
    }
}

Then in the Application_UnhandledException event handler, I wanted to show the exception message to the users:

private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
{
    if (e.ExceptionObject is MyException)
    {
        // Show all MyException's message to the user.
        e.Handled = true;
        MessageBox.Show(e.ExceptionObject.Message);
    }
    else
    {
        // Handle other exceptions here.
    }
}

This looks good enough except one problem, the exception will never end up in the Application_UnhandledException event handler. This is because in the MVVM Light view model locator (by default the ViewModelLocator.cs file), uses a static reference of your main model to bind data to your UI components. static reference is probably running in a different system thread then your instantiated UI components. So when you raise your exception in your view model, the exception won’t reach any event handlers that are in a different thread.

The solution to this problem is rather simple: you raise the exception in the same UI thread.

private int _price;
public int Price
{
    get { return _price; }
    set
    {
        if (value < 0)
        {
            // Throw the exception in the UI thread.
            App.Current.RootVisual.Dispatcher.BeginInvoke(() => { throw new MyException("Price cannot be less than 0."); });
            // Prevent the property from being set to the incorrect value.
            return;
        }
        _price = value;
        RaisePropertyChanged("Price");
    }
}

The modified property uses the Dispatcher object of the current application’s RootVisual, which is usually your Main Page. The BegainInvoke function will throw the exception in the same thread of the RootVisual, which would be the same thread as your application. Thus making the exception catchable in the application’s Application_UnhandledException event handler.

Note that BeginInvoke executes the action in another thread. This is an asynchronous operation that does not interrupt your current execution. So you usually need to put in the extra “return;” statement to manually interrupt the execution if you need to. This is not necessary in a normal case since raising an unhandled exception only interrupts the execution process in it’s own thread.

Note: Catching exceptions in Application_UnhandledException may raise performance concern. If you are a Windows Phone 7 developer, you should test your exception catching performance on a real device. In most cases, this will cause perceivable slowness and is usually not a recommended approach.

WP7: How To Create Beautiful Page Transition In 5 Minutes

If you ever wanted to create transition animations like the native hubs in Windows Phone 7, then there are 2 really simple ways to do so:

Using the Sliverlight for Windows Phone 7 Toolkit

  • First, of course you need to download the toolkit.
  • Add the reference Microsoft.Phone.Controls.Toolkit to your project.
  • Then you need to modify your App.xaml.cs file. Find the line where it sets the RootVisual to:
    RootFrame = new Microsoft.Phone.Controls.TransitionFrame();
    
  • Now you can add the transition in the page you want by adding the following code in your page XAML:
    1. Add the XML name space for toolkit in your page first if it is not already presented:
      xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"
      
    2. Add the following XAML right under your page element
      <toolkit:TransitionService.NavigationInTransition>
          <toolkit:NavigationInTransition>
              <toolkit:NavigationInTransition.Backward>
                  <toolkit:TurnstileTransition Mode="BackwardIn"/>
              </toolkit:NavigationInTransition.Backward>
              <toolkit:NavigationInTransition.Forward>
                  <toolkit:TurnstileTransition Mode="ForwardIn"/>
              </toolkit:NavigationInTransition.Forward>
          </toolkit:NavigationInTransition>
      </toolkit:TransitionService.NavigationInTransition>
      <toolkit:TransitionService.NavigationOutTransition>
          <toolkit:NavigationOutTransition>
              <toolkit:NavigationOutTransition.Backward>
                  <toolkit:TurnstileTransition Mode="BackwardOut"/>
              </toolkit:NavigationOutTransition.Backward>
              <toolkit:NavigationOutTransition.Forward>
                  <toolkit:TurnstileTransition Mode="ForwardOut"/>
              </toolkit:NavigationOutTransition.Forward>
          </toolkit:NavigationOutTransition>
      </toolkit:TransitionService.NavigationOutTransition>
      

    Note that in the above example, the transition we are adding is the most common “Turnstile Transition”. There are also other transition available from the toolkit, they are: turnstile, slide, rotate, swivel, and roll.

Using the Telerik RAD Control for Windows Phone

Telerick’s solution is quite similar to the above but providing more transition options and less code required.

Note that by the time of writing, the control is still at beta stage. Therefore, it is unknown that if the behaviors would change in future releases.

  • First, get the control here and install it.
  • You need to add the reference Telerik.Windows.Controls.Primitives and Telerik.Windows.Core to your project, which is usually located at C:\Program Files\Telerik\RadControls for Windows Phone 7 [release time]\Binaries\WindowsPhone.
  • Similar to the toolkit example, modify your App.xaml.cs file:
    RootFrame = new Telerik.Windows.Controls.RadPhoneApplicationFrame();
    

    This is it! If you only need the turnstile transition like the native windows phone 7 hubs. The RadPhoneApplicationFrame has the turnstile transition by default. Alternatively, you can also set your desire transition in code:

    RadPhoneApplicationFrame frame = new RadPhoneApplicationFrame();
    frame.Transition = new RadTurnstileAndSlideTransition();
    RootFrame = frame;
    

Of course you can also manually specify different transition for each page. In the page you want to specify the transition, you simply put the following XAML code:

  1. Add the XML name space for telerik controls in your page first if it is not already presented:
    xmlns:telerikPrimitives="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Primitives"
    
  2. Add the following XAML right under your page element:
    <telerikPrimitives:RadTransitionControl.Transition>
        <telerikPrimitives:RadTurnstileTransition/>
    </telerikPrimitives:RadTransitionControl.Transition>
    

Similar to the toolkit, Telerik has transitions other than turnstile. Look in the Object Browser of Visual Studio or play around with the installed demo to see more of them.

Style the transition for every page

An alternative way to apply transition to every page in your project, instead of copy-pasting some redundant code block, why not make them into a style in your application resource directory so that all pages can use them. Take the Toolkit solution as an example, in your App.xaml, simply add:

<Application.Resources>
    <Style x:Key="PageStyle" TargetType="phone:PhoneApplicationPage">
        <Setter Property="toolkit:TransitionService.NavigationInTransition">
            <Setter.Value>
                <toolkit:NavigationInTransition>
                    <toolkit:NavigationInTransition.Backward>
                        <toolkit:TurnstileTransition Mode="BackwardIn"/>
                    </toolkit:NavigationInTransition.Backward>
                    <toolkit:NavigationInTransition.Forward>
                        <toolkit:TurnstileTransition Mode="ForwardIn"/>
                    </toolkit:NavigationInTransition.Forward>
                </toolkit:NavigationInTransition>
            </Setter.Value>
        </Setter>
        <Setter Property="toolkit:TransitionService.NavigationOutTransition">
            <Setter.Value>
                <toolkit:NavigationOutTransition>
                    <toolkit:NavigationOutTransition.Backward>
                        <toolkit:TurnstileTransition Mode="BackwardOut"/>
                    </toolkit:NavigationOutTransition.Backward>
                    <toolkit:NavigationOutTransition.Forward>
                        <toolkit:TurnstileTransition Mode="ForwardOut"/>
                    </toolkit:NavigationOutTransition.Forward>
                </toolkit:NavigationOutTransition>
            </Setter.Value>
        </Setter>
    </Style>
</Application.Resources>

Then in each page, you just need to use this style:

<phone:PhoneApplicationPage Style="{StaticResource PageStyle}" ... >

 

Update: With the Feb 2011 release of the Toolkit, its page transition animations are using better easing functions. Due to the fact that Telerik’s controls are still in beta stage, and there would probably be licensing costs when you need to use it commercially, I recommend the toolkit option.