Andrej Tozon's blog

In the Attic

NAVIGATION - SEARCH

Named & optional parameters in Silverlight 4

Named & optional parameters are a new C# language feature coming up with .NET FX 4.0 and guess what… it’s in Silverlight 4 as well!

Optional parameters will come very useful when defining complex APIs where you would usually have to provide several overloads for the same method for it to make sense to wide variety of usages. Let’s take a look at this basic example:

public void PositionWindow(bool isTopMost, double left = 0, double top = 0, double width = 800, double height = 600)
{
    Window window = Application.Current.MainWindow;
    window.TopMost = isTopMost;
    window.Left = left;
    window.Top = top;
    window.Width = width;
    window.Height = height;
}

isTopMost is the only parameter that’s required, all other parameter specify their default value, which makes them optional. Needless to say, the default values will be used for those parameters which the calling function doesn’t provide. One thing to know is that optional parameter must always be declared after required parameters.

The following calls are all valid:

PositionWindow(true); // position and size set to defaults
PositionWindow(true, 100); // top position and size set to defaults
PositionWindow(true, 100, 200); // sizes set to defaults
PositionWindow(true, 100, 200, 600, 200); // all parameters provided

But what if you wanted to provide the size only and leave the position to be set to defaults? Enter named parameters. The same method above can be called also with:

PositionWindow(isTopMost:true, width: 600, height: 200); // named parameters
PositionWindow(true, width: 600, height: 200); // naming is optional when positioned right
PositionWindow(true, height: 200, width: 600); // order doesn't matter
PositionWindow(height: 200, width: 600, isTopMost: true); // ... even with the required parameters

Simple, eh? The need for named and optional parameters may have come from the need to simplify COM automation, but they may prove just as useful in many other cases. But before you go start creating methods with tens of optional parameters, note that this is not the ultimate solution, and one thing worth noting is although the calls above look like they are passing the specified parameters only, the compiler in fact generates them with all parameters in place. This is how the Reflector sees that last batch of calls:

bool CS$0$0000 = true;
double CS$0$0001 = 600.0;
double CS$0$0002 = 200.0;
this.PositionWindow(CS$0$0000, 0.0, 0.0, CS$0$0001, CS$0$0002);
CS$0$0001 = 600.0;
CS$0$0002 = 200.0;
this.PositionWindow(true, 0.0, 0.0, CS$0$0001, CS$0$0002);
CS$0$0001 = 200.0;
CS$0$0002 = 600.0;
this.PositionWindow(true, 0.0, 0.0, CS$0$0002, CS$0$0001);
CS$0$0001 = 200.0;
CS$0$0002 = 600.0;
CS$0$0000 = true;
this.PositionWindow(CS$0$0000, 0.0, 0.0, CS$0$0002, CS$0$0001);

Potential architectural issues aside, I’m quite happy to see this feature come to Silverlight as well. How about you?



Putting Silverlight tweets on the map

Twitter Maps application was updated last night to allow embedding custom Twitter maps on web sites. The process of creating a custom Twitter map is fairly easy, these are the steps for creating a Silverlight tweets map.

1. Go to the Bing Maps site, click on the MAP APPS button and select the Twitter Maps application:

image

The Twitter Maps application will open, showing you the location of the most recent tweets in your area. Of course, only geotagged tweets will be shown on the map.

2. Click on the plus sign on the left side to open the Search Filters panel:

image

3. Type “silverlight” into the keywords field and click Submit:

image

4. Click the Embed in your site button, found at the bottom of the left column:

image

… and the embedding dialog window will show up.

5. Select Anywhere for the Map Location and check that the Current Filters is set to “silverlight”:

image6. Copy the provided HTML code into your site.

And this is how this Silverlight tweets map looks like:

Using different filters and settings will get you a whole lot of alternatives for creating your own Twitter map. With geotagging getting more popular by the day, your maps will be getting richer along the ride.



Add version 4 components to your Silverlight 3 application with MEF

Note: this post and accompanying source code was updated to reflect the latest MEF build on Codeplex. This build is much more aligned with the version of MEF that is available from Silverlight 4 Beta SDK.

The current Silverlight version is v3, with v4 in the making (in Beta 1 at the time of this posting). Silverlight 4 is bringing a lot of new features in the core framework and to use them, you would have to migrate your applications to the latest version, once it gets released. And that would require all the potential users to upgrade their machines to the latest version as well.

But there’s another way. By using MEF (Managed Extensibility Framework), you can extend your existing Silverlight 3 application with optional package, which would contain Silverlight 4 components only.

Here’s an example: user can select an image file from your local disk in Silverlight 3 only through an OpenFileDialog, while with the new drag/drop feature in Silverlight 4, she would be able drag a picture from the file system and drop it onto the application. Why not allow those with Silverlight 4 installed do it the easy way?

To make this work, the main application should be all Silverlight 3. We’d provide additional Silverlight 4 features in a separate XAP package, which would be downloaded later and tested for the right runtime version. In case user had the latest Silverlight runtime installed, we could bring in additional features in the application. For this post, I’m going to implement the abovementioned picture select feature by providing two controls:

  • a select button for choosing the picture through an OpenFileDialog (Silverlight 3 feature)
  • a drop canvas where user can drop the picture from the file system (Silverlight 4 feature)

Silverlight 3 control

Here’s how the BrowseForPictureControl would look like:

imageThis control would be contained in the main application. It exposes the PictureSelected event, with the FileInfo data passed as an event argument. Because the application is going to subscribe to this event for each control that exposes it, we need to make an interface for it and put that into a new project that would be shared among the both packages.

public interface IPictureControl
{
    event EventHandler<PictureSelectedEventArgs> PictureSelected;
}

public class PictureSelectedEventArgs : EventArgs
{
    public FileInfo File { get; set; }

    public PictureSelectedEventArgs(FileInfo file)
    {
        File = file;
    }
}

The control implements the this interface as:

private void OnBrowse(object sender, RoutedEventArgs e)
{
    OpenFileDialog dialog = new OpenFileDialog();
    bool result = dialog.ShowDialog() ?? false;
    if (result)
    {
        OnPictureSelected(dialog.File);
    }
}

Silverlight 4 control

The improved Silverlight 4 control should be created in a new Silverlight 4 application project, that would be disconnected from the main project, but referencing the previously created shared project. The control looks simpler too:

image

And the interface implementation:

private void OnDrop(object sender, DragEventArgs e)
{
    IDataObject dataObject = e.Data as IDataObject;
    if (e.Data == null)
    {
        return;
    }
    FileInfo[] files = dataObject.GetData(DataFormats.FileDrop) as FileInfo[];

    OnPictureSelected(files[0]);
}

OK, controls done. Now, on to MEF.

Bringing in MEF

MEF for Silverlight 3 is available for download from Codeplex. You’ll need the following assemblies added as a reference in your main application:

  • System.ComponentModel.Composition
  • System.ComponentModel.Composition.Initialization.dll

The second assembly is only required to use from the main project, where composition is performed. The project that is shared between the SL3 and SL4 projects can reference just the first assembly from the list. Also, one downside of maintaining the compatibility with Silverlight 3 is that the Silverlight 4 project must reference the same System.ComponentModel.Composition assembly as other projects. No ‘native’ SL4 MEF there…

Attribute for version

Obviously, loading any Silverlight 4 based code into a Silverlight 3 application should be impossible, therefore we need to mark both of controls with information about the Silverlight runtime they require. Something in a way of:

[ExportablePictureSelector(RequiredVersion = "3.0")]
public partial class BrowseForPictureControl : UserControl, IPictureControl
{
    ...
}

for Silverlight 3 control, and:

[ExportablePictureSelector(RequiredVersion = "4.0")]
public partial class DragDropPictureControl : UserControl, IPictureControl
{
    ...
}

for Silverlight 4 control.

The ExportableSelector attribute is derived from MEF’s ExportAttribute and is declared as:

[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class ExportablePictureSelectorAttribute : ExportAttribute, IPictureSelectorMetadata
{
    public ExportablePictureSelectorAttribute()
        : base(typeof(IPictureControl))
    {
    }

    public string RequiredVersion { get; set; }
}

Putting it all together

The main application provides a catalog of all the controls that were discovered:

[ImportMany(AllowRecomposition = true)]
public ObservableCollection<Lazy<IPictureControl, IPictureSelectorMetadata>> PictureControls { get; set; }

The PictureControls collection will change whenever a new export is discovered by MEF. When that happens, the newly discovered control will be added to the main form:

private void OnPictureControlsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    foreach (Lazy<IPictureControl, IPictureSelectorMetadata> view in Views)
    {
        Control c = view.Value as Control;
        if (!panel.Children.Contains(c) && Application.Current.Host.IsVersionSupported(view.Metadata.RequiredVersion))
        {
            panel.Children.Add(c);
            view.Value.PictureSelected += OnPictureSelected;
        }
    }
}

The above code shows that the main criteria for adding the control on the form is that it’s RequiredVersion is supported by the runtime – and that is checked with the interop IsVersionSupported method of the plugin host.

When picture is selected, the PictureSelected event is fired by the control and handled to display the picture:

private void OnPictureSelected(object sender, PictureSelectedEventArgs e)
{
    BitmapImage bi = new BitmapImage();
    bi.SetSource(e.File.OpenRead());
    image.Source = bi;
}

Of course, BrowseForPictureControl control being included in the main project, it will immediately be picked by MEF and inserted in the PictureControls collection. For Silverlight 4 based XAP package, however, we need to download it first. Here’s the InitializeContainer method, which initializes a new composition container and triggers the package download:

private void InitializeContainer()
{
    PackageCatalog catalog = new PackageCatalog();
    catalog.AddPackage(Package.Current);
    CompositionContainer container = new CompositionContainer(catalog);
    container.ComposeExportedValue(catalog);

    CompositionHost.InitializeContainer(container);

    Package.DownloadPackageAsync(new Uri("CrossVersioning.Version4Enhancements.xap", UriKind.Relative), (e, p) =>
    {
        if (p != null)
        {
            catalog.AddPackage(p);
        }
    });

    PartInitializer.SatisfyImports(this);
}

The Silverlight 4 package is asynchronously downloaded from the server and added to the package catalog. The last line is there to start the initial composition, causing the v3 control to immediately show up.

Conclusion

There… the application is set up. Users, having the Silverlight 3 runtime installed, will see the it as:image… and Silverlight 4 users will also see that additional feature:

image

This approach will let you gradually update your applications to use Silverlight 4, not forcing the users to update to the latest runtime immediately (although there would probably be no reason not to ;))

You can test the application right here:

Or download the source code from here. Enjoy.



Shidonni - Silverlight-based creative playground for your children

I stumbled upon this really nice Silverlight application today – Shidonni is a sort of social networking application for creative children – it lets them create their own animals, put them in a world that they’ve created, feed them with the food they’ve drawn and share them with their friends on the internet. A wide range of games is available, where children play with their own creations and compete with each other.

The application seems to be around for over a year now, but there was this extra which caught my attention. Since last November, Shidonni offers a service of making real plush toys from your child’s creations!

image

Shidonni appears to be one of the larger freely available Silverlight applications out there on the net, its features making it a good use case for Silverlight.



My MEF articles published on SilverlightShow

My two-part article on rebuilding an existing Silverlight application to use MEF (Managed Extensibility Framework) for “selective composition” is now live on SilverlightShow.net (part 1, part 2). I took my Halloween Gallery application and made it pluggable so I can pull in different themes throughout the whole year (current themes include Halloween and Christmas).

Halloween Live Gallery Christmas gallery 

The original features are still there – geotagged photos are retrieved from Flickr API and the location where they were shot is shown on the Bing Map. If you’re interested in MEF, take a look at let me know what you think. The application will be released to Codeplex soon.



SilverlightShow Eco Contest

SilverlightShow.net is running a SilverlightShow Eco Contest! Write a Silverlight-based application that helps support and promote environment-friendly activities, and you can win great prizes, including a trip to MIX10 event in Las Vegas (MIX10 pass, 3-night hotel stay at Mandalay Bay Hotel and 1,000 USD for travel expenses included).

Read official rules here. But hurry, the contest ends on February 15th, 2010.



Display “My Pictures” in Silverlight application at design time

Following up on The ultimate hack for Silverlight in Blend post from Josh Smith, I tried to make Blend display pictures from the My Pictures folder right in my Silverlight application. Needless to say, it worked as advertised :)

Blend

The ViewModel is set through d:DataContext:

public class MainPageViewModel
{
    public MainPageViewModel()
    {
        SetLocalPictures();
    }

    private void SetLocalPictures()
    {
        string folder = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
        IEnumerable<string> pictures = Directory.EnumerateFiles(folder);
        Pictures = (
            from p in pictures 
            select new Uri(string.Format("file://{0}", p.Replace('\\', '/')), UriKind.Absolute)
            ).ToArray();
    }

    public Uri[] Pictures { get; set; }
}

The thing is that this code wouldn’t work with Silverlight application running in a non-trust mode – it would throw a security exception. However, setting this ViewModel as the run-time DataContext and running with elevated permissions, the pictures would get displayed as well.

And of course this works in Visual Studio 2010 designer too:

VS2010

A nice alternative for Blend’s sample data…



My articles on SilverlightShow

A few of my Silverlight articles were published on the SilverlightShow site this past two months. The first one is an introduction to Silverlight/(WPF)/Blend behaviors, where I create a Silverlight Halloween Sound Player without writing a single line of code – the application is composed entirely in Expression Blend, using various behaviors.

Halloween Sound Player

I also used behaviors for another article, to showcase some of the new Silverlight 4 features: WebCam capture support, printing, drag/drop, clipboard, commanding, some databinding enhancements and implicit styling support. The result is a nice doodling application, which can be used to entertain your kids.Camdoodle

The third article was about creating a Europe Weather Map with Silverlight, showing current weather conditions for some of the larger cities in Europe. It was mostly about using the Bing Maps Silverlight Control SDK, but fun anyway.

Europe Weather map

You can expect more articles appearing on SilverlightShow in the next days/months. Leave a comment if you find them useful.



Silverlight 4 WebCam zoom

Fooling around with Silverlight’s WebCam support. The application below will let you zoom in and out of WebCam capture and pan around. Nothing special, just a quick POC for the project I’m building. Silverlight 4 required.



Developers, please mind the locale!

I’m observing this really irritating trend with new software lately…

I followed up on a couple of tweets today to try the new Silverlight application everyone was RT’ing of. Clicked on the link and the loading animation began. Seconds later, it… stopped.

Huh?

Then I noticed an icon in IE’s left bottom corner…

image

The following detailed message confirmed my assumptions about what caused the error:

image

“Input string was not in a correct format”!

I’m sure that if you live outside US/UK and follow Silverlight community, you have encountered this error before. For example, I’ve been to at least two online events in the past year, with live streaming content delivered over a Silverlight player, which displayed this very same error when launched.

Here is the list of some other apps that I’ve worked with recently, that have been showing the same symptoms. To name just a few:

Silverlight Bing Maps, specifically the Twitter app – can you find the difference between these two links?

http://www.bing.com/maps/explore/#5872/style=auto&lat=46.037671&lon=14.533958&z=11&
pid=5874/5003/0.40326=s&o=&a=0&n=0

and

http://www.bing.com/maps/explore/#5872/style=auto&lat=46,037671&lon=14,533958&z=11&
pid=5874/5003/0.40326=s&o=&a=0&n=0

The first link uses a dot as a decimal separator and will work for English locales, while the second one uses commas and will work for non-English locales (speaking generally). Note that URL will be converted to the default format when application is loaded, probably throwing you somewhere in an ocean, if the numbers weren’t in the expected format.

Live Labs Pivot (desktop app) will crash on startup when locale is not set to English.

Six-Degrees Search is the application I’ve tried to run today. A Silverlight app, based on the EntityCube entity search engine and being developed by Microsoft Research. Regional settings need to be set to English locale for application to load correctly.

Mentioned software might be labeled Beta or prototype, but that hardly justifies the fact that developers didn’t support non-English locales from the very start. Therefore I’m taking this blog post to appeal to all Silverlight developers, especially those working with regional settings set to English natively:

Please, make your applications respect local regional settings as early in the development as possible. Silverlight may be cross-platform and cross-browser, but developers, not taking local regional settings into the account, don’t even make it cross-locale.

Just in case anyone encounters a weird behaving application, showing symptoms described at the very top of this post, this is one of the things to try first: The most likely cause for the above error is a wrong date or number format. Changing your local regional settings will probably help:

image