Andrej Tozon's blog

In the Attic

NAVIGATION - SEARCH

Silverlight, Prism EventAggregator and “lost events”

I’ve just started discovering Prism, mainly as a tool to help me use the MVVM with my apps. That said, by now, Prism proved itself with:

  • Support for Commanding
  • EventAggregator
  • Unity integration
  • Targeting both WPF and Silverlight

EventAggregator is great for inter-VM communication, but only when subscribing VM(s) is/are alive (instantiated) when publishing VM publishes the event. I may be wrong here (please somebody correct me), but I haven’t found a way for a newly instantiated subscriber VM get to already broadcasted event, which was published before the instantiation. The example here would be a new dialog window, with its VM wanting the last value that parent’s VM published before dialog was created (a selected ListBox value, for example). Sure, the publisher could publish the same event again after the dialog is created, but this would confuse things up because there may be other listeners subscribed to it and perhaps wouldn’t know how to handle the exact same event.

To solve this issue, I created a new class, deriving from the CompositePresentationEvent<T> and called it CachingCompositePresentationEvent<T>. The implementation is simple:

public class CachingCompositePresentationEvent<T> : CompositePresentationEvent<T>
{
    public bool HasValue { get; private set; }

    private T lastPayload;
    public T LastPayload
    {
        get
        {
            if (!HasValue)
            {
                throw new InvalidOperationException();
            }
            return lastPayload; 
        }
        private set
        {
            lastPayload = value;
            HasValue = true;
        }   
    }

    public override void Publish(T payload)
    {
        LastPayload = payload;
        base.Publish(payload);
    }
}

The HasValue will return true when at least one event was published at the time, and LastPayload will return the payload, included in the last published event.

If the event is declared as:

public class MyCachingEvent : CachingCompositePresentationEvent<int> { }

… then getting to its value would be:

MyCachingEvent ev = aggregator.GetEvent<MyCachingEvent>();
if (ev.HasValue)
{
    int value = ev.LastPayload;
}

This is the basics, there's plenty of room for improvement - like adding a Clear() method to clear the last payload value or clear it automatically on the first LastPayload read - just to clear the memory, when payload types aren’t simple/small.

Shout it

Countdown to Silverlight 3 #15: UI Virtualization

Silverlight 3 includes a new type of a StackPanel, called VirtualizingStackPanel. VirtualizingStackPanel enables UI virtualization and is now the default items panel for the ListBox, with virtualization option enabled.

If you want to turn UI virtualization in ListBox to off, set its VirtualizingStackPanel.VirtualizationMode to Standard (the default is Recycling). The embedded VirtualizingStackPanel will in this case behave as a plain old StackPanel.

VirtualizingStackPanel can be used with any ItemsControl, but it can’t be used on its own (like putting in on a page and manually cram a couple thousand of items on it as you could do with ordinary StackPanel). But the interesting thing is it is derived from an abstract class called VirtualizingPanel, which means the ability to create new kinds of virtualizing panels (!)

The following example shows the difference between Virtualization modes. I intentionally created a heavier item template for the UI, so difference would be more obvious. Try scrolling both ListBoxes to see how UI virtualization impacts the scrolling performance.

UI Virtualization

Run the application online

Source code below:



Countdown to Silverlight 3 #14: Selector.IsSynchronizedWithCurrentItem

Silverlight 3 puts the ICollectionView interface to some serious use and brings us the CollectionViewSource class, which provides a view on top of the data collection, meaning you can sort, filter or group your items within your view, without actually changing the underlying data. One artifact, coming with the class, is the IsSynchronizedWithCurrentItem property, which enhances the collection with a notion of a currently selected item. When Selector’s IsSynchronizedWithCurrentItem property is set to true, all other controls, bound to the same collection, are kept in sync with the selected item. Silverlight’s implementation is a bit different than WPF’s. You can’t set IsSynchronizedWithCurrentItem property to true by yourself, the value is determined from your Items source. If it implements the ICollectionView interface, then it’s going to be synchronized, unless explicitly turned off (with setting the property to false).

For this example, I created three ListBoxes, all bound to the CollectionViewSource. Two of them are kept in sync, the third one is not because it’s IsSynchronizedWithCurrentItem property is set to false. I put up a few additional TextBlocks, bound to other item properties, to show the synchro-magic going on behind all this.

There’s more to ICollectionView interface, but that’s also another post…

Run the application online

Source code below:

Countdown to Silverlight 3 #13: Bitmap effects

Silverlight 3 shipped with 2 built-in bitmap effects that can be applied to any UIElement – those are DropShadow and Blur. But not to worry, we can create and use a lot more effects, because these are pixel shaders, compatible with the ones built for WPF. There are quite a few WPF (now even including SL support) effects libraries out there and I will be looking at those in one of the future posts. This time, it’s only this simple and very straightforward example, showing off the two built-in effects.

SL3 Bitmap effects

Run the application online

Source code below:

Countdown to Silverlight 3 #12: ClearType font rendering

Text readability is very important for any LOB application and since Silverlight 3 is aimed towards creating LOB apps, Microsoft decided to address the readability issue by supporting ClearType in the final SL3 release. The best thing is – it’s on by default, but you can turn it off when you’re about to perform some kind of animation with it. Turning the ClearType off will improve the text rendering performance when animating it, since antialiasing requires some additional calculations and performing that for several times per second might result in a jerky animation. To turn the rendering optimization off, set the TextOptions.TextHintingMode property to Animated. To turn it back on after you’re done with the animation, you can either clear the property or set it to Fixed.

SL3 ClearType

Run the application online

Source code below:

Countdown to Silverlight 3 #11: Writeable Bitmap

Want to create a new bitmap image in Silverlight? Want to capture a part of your application and use it as a brush? Silverlight has an answer for you – WriteableBitmap is a BitmapSource-derived class that you can manipulate in the runtime, either by rendering UI elements on it or by manipulating pixels manually. The example (below) will show how to capture a movie frame or an entry form, along with altering some pixels on the captured image – try moving your mouse over either of the captured images.

Run the application online

Source code below:

Countdown to Silverlight 3 #10: Animation easing

Doing non-linear animations with Silverlight 2 involved “playing” with key splines, and it took quite some time to get it right, even if using a tool like Expression Blend. Silverlight 3 puts some ease in this process by introducing the new, predefined, so-called easing functions, that can be applied to an animation to affect its state while progressing through time. It’s similar to what you could achieve with the splines, but without the fuss. The functions include some standard progressions (Circle, Cubic, Exponential, Quadratic, etc), with a couple of more interesting ones (Back, Elastic).

If the provided functions not enough for you, you can create your own function by creating a new class, deriving from the EasingFunctionBase class. I’ve created a “JerkyEase” animation, which is really a very simple linear animation, but with a random jerky-interrupty points to make it look… well, kind of underperformant. Totally useless, but it made it into the sample deck until I figure out something more usable.

Run the application online

Source code below:

Countdown to Silverlight 3 #9: Day 0 and updated sample deck

After a week of spending my holidays, enjoying the sun and playing on the beach with my kids, it’s time to continue the Silverlight 3 countdown series… In the meantime, Silverlight 3 was officially released (it’s probably best to only reference the “Cream” of the SL3 release posts here, in case you missed all the fun, like I did).

I updated my Countdown sample application to match the SL3 RTW bits, with all the necessary changes, most of them having to do with OOB API changes (read more about SL2/SL3B breaking changes here). Visual Studio is now also providing a nice new settings screen for describing your OOB application.

OOB

I’ll continue adding more examples of SL3 new features in the future.

Congrats and thanks to everybody having their part in getting the Silverlight 3 release ready and out so soon after the initial release.

Run the updated application online[SL3RTW required]

Source code below:

Countdown to Silverlight 3 #8: Style inheritance

Silverlight 3 supports style inheritance through setting the BasedOn property. Although not as powerful as that in WPF, using this feature can significantly improve the maintainability of application styles – instead of duplicating several properties when creating similar styles, you can define one base style, set some common properties, then create a a derived style, inheriting those properties and adding new ones.

When defining a new style, the BasedOn property an be used to reference a base style, thus extending it with new properties. All you have to be careful about is to target the same type (or its derivate) as the base style. For example, you can’t create a new style, targeting a Button, if the base style targets a TextBox. You can, however, target a Button, if the base style targets a Button, ButtonBase, ContentControl, etc (ascendants of a Button). You can also overwrite property values, set in a base style – either in a derived style, or by setting it directly on a control.

The example below covers some of the mentioned scenarios.

Style inheritance

Run the application online

Source code below:

Countdown to Silverlight 3 #7: Navigation

Another powerful Silverlight 3 feature is navigation. The concept is very simple: provide a space on your main page, which you’ll later fill with custom content – pages. You’ll be able to navigate through these pages (by using browser’s Forward/Back buttons, directly access them and even provide custom parameters.

There’s a special project template in Visual Studio 2008 to create a Silverlight Navigation application and it provides a good start if you’re new with this feature – you’ll get a nice template to get you going, which you’ll be able to customize as you go forward.

There is one core control that you’ll need to enable this feature – System.Windows.Controls.Frame, which will host your pages by navigating to them. A Page is a special control, derived from UserControl, adding navigation capabilities.

I refactored my Silverlight 3 features application to a Navigation application, each sample being a separate page, accessible from a list of samples. I’ll continue to add new samples to this application in the future. I’ll try to maintain the main application (as well as the examples pages) to be as much MVVM-ish as possible, but without having to resort to any external dependencies.

A couple of things to note in the new, refactored application:

1. By using Element binding feature to bind the Frame Source to selected Url in the samples list, calls to Navigate() method aren’t required – binding does all the magic.

...
<ListBox x:Name="views"
           ItemsSource="{Binding Links, Source={StaticResource viewModel}}" ... />
...
<navigation:Frame Source="{Binding SelectedItem.Value, ElementName=views}" ... />
...

2. Passing custom parameters to a page. MergedResourceDictionaries page has been modified so it accepts a parameter of a theme to be applied to the sample form.
Example: http://tozon.info/sl3/#/Views/MergedResourceDictionaries.Xaml?style=Red

3. Uri mapping. Parameters for MergedResourceDictionaries can be passed in to the paged in a shorter form, thanks to the Uri mapper.
Examples: http://tozon.info/sl3/#Form/Red| http://tozon.info/sl3/#Form/Blue

4. To prevent any mis-addressing of navigation pages, attach a handler to frame’s NavigationFailed event and handle those cases to spare your users from seeing some nasty popup windows, telling them they misspelled the url.

private void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
{
e.Handled = true;
views.SelectedIndex = 0;
}

Silverlight 3 navigation feature greatly simplifies creation of modern, interactive web sites with multiple pages, where previous to SL3, ASP.NET was in lots of cases the first choice.

Additional reading
http://timheuer.com/blog/archive/2009/03/22/silverlight-navigation-framework-and-uri-routing.aspx

http://blogs.microsoft.co.il/blogs/alex_golesh/archive/2009/04/02/
silverlight-3-quick-tip-6-navigation-framework-and-uri-routing.aspx

Run the sample online

Source code below: