Colin Eberhardt's Technology Adventures

Everything you wanted to know about databinding in WPF, Silverlight and WP7 (Part One)

April 5th, 2012

OK, so the title is a little ambitious, but there is nothing wrong with setting yourself lofty aims! Because of the depth of this topic I have decided to split this tutorial up into a series of blog posts, each of which explore a different aspect of the binding framework.

I don’t usually write tutorial blog posts and series, preferring instead to develop new controls or novel techniques. However, I really felt this subject needed an in-depth tutorial. Databinding is a fundamental part of the WPF, Silverlight and the Silverlight for Windows Phone 7 frameworks. It is a powerful concept that once mastered allows you to write concise and elegant code. Yet for all its power, it is a little complex and that is my reason for launching into this blog series.

The rough outline for this series is as follows:

  • Part One – Life before binding, INotifyPropertyChanged and creating bindings in code-behind
  • Part Two – The binding markup extensions, the DataContext and path syntax
  • Part Three – Other binding sources, ElementName, TemplatedParent, TemplateBinding
  • Part Four – Value converters
  • Part Five – List binding

Life before binding

To understand what databinding is and the service it provides us with, it is worth looking at how you wire-up a user-interface without using databinding. We’ll start with a simple model object, or business object, and see how we can take the properties that this object exposes and display them in the UI using standard controls. We will also see how we can respond to event raised by these controls in order to update our model.

Note, that I am making the assumption that your code will contain some sort of model object. This doesn’t have to be the case! You could store your data within the UI controls directly, however this rapidly becomes un-maintainable. There are a whole host of UI patterns that have been developed in order to keep the model and the view separate (MVP, MVC, MVVM etc…)

We’ll look at how to manage the interactions between the model and the view without the help of a binding framework. For our example we’ll look at a very simple UI which displays the details of an event, its name and the date of the event:

The model that supports this view is shown below:

/// <summary>
/// A simple model object that represents an event
/// </summary>
public class EventModel : INotifyPropertyChanged
{
  private string _title;
 
  /// <summary>
  /// Gets / sets the event title
  /// </summary>
  public string Title
  {
    get { return _title; }
    set
    {
      if (value == _title)
        return;
 
      _title = value;
      OnPropertyChanged("Title");
    }
  }
 
  private DateTime _date;
 
  /// <summary>
  /// Gets / sets the date of this event
  /// </summary>
  public DateTime Date
  {
    get { return _date; }
    set
    {
      if (value == _date)
        return;
 
      _date = value;
      OnPropertyChanged("Date");
    }
  }
 
  public event PropertyChangedEventHandler  PropertyChanged;
 
  protected void OnPropertyChanged(string propertyName)
  {
    if (PropertyChanged != null)
    {
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
  }
}

In our case the model implements INotifyPropertyChanged, allowing us to detect changes in its properties. We will use this to update the view when the model changes.

The view has the following XAML (with the various layout properties omitted for clarity):

<TextBlock Text="Name:"/>
<TextBox x:Name="EventTitle"
          TextChanged="EventTitle_TextChanged"
 
<TextBlock Text="Date:"/>
<sdk:DatePicker x:Name="EventDate"
                SelectedDateChanged="EventDate_SelectedDateChanged"/>
 
<Button Content="Modify Event"
        Click="Button_Click"/>

The code-behind that supports this view is given below:

public partial class MainPage : UserControl
{
  private EventModel _event;
 
  public MainPage()
  {
    InitializeComponent();
 
    // create a model object
    _event = new EventModel()
    {
      Date = new DateTime(2011, 7, 1),
      Title = "Silverlight User Group"
    };
 
    // copy our model object state to the UI
    EventDate.SelectedDate = _event.Date;
    EventTitle.Text = _event.Title;
 
    // 'listen' to changes in the model
    _event.PropertyChanged += Event_PropertyChanged;
  }
 
  /// <summary>
  /// Handles changes in the model, reflecting this change in the UI (view)
  /// </summary>
  private void Event_PropertyChanged(object sender, PropertyChangedEventArgs e)
  {
    if (e.PropertyName == "Title")
    {
      EventTitle.Text = _event.Title;
    }
    if (e.PropertyName == "Date")
    {
      EventDate.SelectedDate = _event.Date;
    }
  }
 
  /// <summary>
  /// Handles the TextChanged event updating the model accordingly
  /// </summary>
  private void EventTitle_TextChanged(object sender, TextChangedEventArgs e)
  {
    _event.Title = EventTitle.Text;
  }
 
  /// <summary>
  /// Handles the SelectedDateChanged event updating the model accordingly
  /// </summary>
  private void EventDate_SelectedDateChanged(object sender, SelectionChangedEventArgs e)
  {
    _event.Date = EventDate.SelectedDate.Value;
  }
 
  private void Button_Click(object sender, RoutedEventArgs e)
  {
    // make some change to our event
    _event.Title = _event.Title.ToLower();
    _event.Date = _event.Date.AddDays(1);
  }
}

In order to wire-up the model with our view, the above code performs the following distinct tasks for each of the model’s properties:

  1. Sets the state of the UI controls to the initial state of the model. In the above example this is done in the constructor.
  2. Subscribes to the event that the UI control exposes to indicate a change in state. For the TextBox this is the TextChanged event, for the DatePicker this is the SelectedDateChanged event. When a change occurs, the UI state used to update the mode.
  3. Subscribes to PropertyChanged events from the model object. The handler for this event detects the property that has changed and updates the state of the corresponding UI control.

If we consider the model object to be the source of the data and the UI control to be the target. We can see that we have three separate flows of data:

The code for each of these three steps is distributed throughout our code, in the constructor and a variety of event handler. For each model property that we wish to expose to our user via the view, we have to add code to perform each of these three tasks. This leads to code that is hard to maintain and dataflow that are hard to trace.

Databinding – less code, greater clarity

Databinding provides an alternative to the manual coupling of the model to the UI controls in our view. The idea being that the binding framework takes care of all three of the tasks above. We simply state that we wish to synchronise a model property with a property of a UI control, and it does the rest. Our complex diagram above simply becomes the following:

Changes in the source property values are pushed to the target property by the binding framework, and (optionally) changes in the target are pushed to the source.

Modifying the code for our example to use the WPF / Silverlight framework results in the following code:

public MainPage()
{
  InitializeComponent();
 
  // create a model object
  _event = new EventModel()
  {
    Date = new DateTime(2011, 7, 1),
    Title = "Silverlight User Group"
  };
 
  // bind the Date to the UI
  EventDate.SetBinding(DatePicker.SelectedDateProperty, new Binding("Date")
  {
    Source = _event,
    Mode = BindingMode.TwoWay
  });
 
  // bind the Title to the UI
  EventTitle.SetBinding(TextBox.TextProperty, new Binding("Title")
  {
    Source = _event,
    Mode = BindingMode.TwoWay
  });
}

This is a big improvement on the previous ‘manual’ example where three separate event handlers were required to maintain synchronization between the model and the view. Databinding allows us to declare how the model is connected to the view, with the databinding framework taking care of the mechanics.

We’ll take a closer look at the databinding syntax in order to understand its various component parts. We can highlight these components by re-writing one of the bindings as follows:

FrameworkElement targetObject = EventTitle;
DependencyProperty targetProperty = TextBox.TextProperty;
object sourceObject = _event;
string sourceProperty = "Title";
 
var binding = new Binding(sourceProperty)
{
  Source = sourceObject,
  Mode = BindingMode.TwoWay
};
targetObject.SetBinding(targetProperty, binding);

From the above we can clearly see the following components:

  • The source object – this is the object which contains the data which we want to render within the UI
  • The source property – the property of the above object which we wish to render
  • The target object – this is a UI control which has a property which we are going to use to display our model property
  • The target property – the property of the UI control which visualises our data
  • The binding - this is used to indicate the source and source property, together with other information relating to the binding like the direction of data flow, value converters etc… (more on these later).
  • SetBinding – this is the method used to associate a databinding with a specific property on the target. Note that the first argument is the dependency property that is defined on TextBox and is public static.

Once a binding has been created and associated with a dependency property, the initial value is propagated from the source to the target. Following this, if the source object implements INotifyPropertyChanged, subsequent changes in the source property value are automatically propagated. If a BindingMode.TwoWay binding is used, changes to the target property, which typically occur due to user interactions, are propagated from the target to the source.

A brief digression into dependency properties

As you can see from the above, databinding is a feature of WPF and Silverlght dependency property mechanism. The type of properties that developers are used to from other .NET languages are typically termed ‘CLR properties’ (Where CLR refers to the Common Language Runtime) so that we know which type of property we are talking about!

CLR properties are simply shorthand for methods used to access a backing field. You cannot use the databinding framework to bind together two CLR properties. Dependency properties are something much more powerful, they provide property inheritance within the visual tree, animation support, precedence rules, coercion and, most importantly for the purposes of this article, databinding.

In the example below, a dependency property ‘TotalGoals’ is defined on a dependency object. By convention, this dependency property is exposed as a public static field on the dependency object. It is this static field that we use to identify the dependency property when binding to it:

public class MatchResult : DependencyObject
{
  /// <summary>
  /// Identifies the TotalGoals Dependency Property.
  /// <summary>
  public static readonly DependencyProperty TotalGoalsProperty =
      DependencyProperty.Register("TotalGoals", typeof(int),
      typeof(MatchResult), new PropertyMetadata(0));
 
}

Once a dependency property has been defined, its value can be get / set via the GetValue / SetValue methods:

var result = new MatchResult();
// set the property
result.SetValue(MatchResult.TotalGoalsProperty, 10);
 
// get the property
Debug.WriteLine(result.GetValue(MatchResult.TotalGoalsProperty))

Because the syntax to get or set a dependency property is not terribly friendly, using the GetValue / SetValue methods, dependency objects typically provide CLR properties that wrap the dependency property access, providing a better API for manipulating the state form code-behind.

/// <summary>
/// Gets or sets the total score. This is a dependency property.
/// </summary>
public int TotalScore
{
  set
  {
    SetValue(MatchResult.TotalGoalsProperty, value);
  }
  get
  {
    return (int)GetValue(MatchResult.TotalGoalsProperty);
  }
}

However, this is purely convention.

Whilst the target for a binding must be a dependency property (which must be defined on a dependency object), the source can be either a dependency property or a CLR property. In practice, unless you are creating your own controls, you will not need to create your own dependency properties. Instead, you will be binding your model to the properties of the various UI elements that are supplied with the WPF / Silverlight frameworks, for example TextBlock.Text. These are all dependency properties.

A quick note about INotifyPropertyChanged

Whilst dependency properties always notify the binding framework of any changes in value, CLR properties only notify of changes if the class which the belong to implements the INotifyPropertyChanged interface (as the class used in the example above does). It is not mandatory that you implement this interface, or raise the PropertyChanged event, for properties that your bind to your UI. However, if you do not, the binding framework will only perform a one-time update, pushing the property value from source to target at the point when the binding is created.

BindingModes

You can specify which direction you want property changes to propagate by setting the BindingMode on a binding. This is probably easiest to illustrate with a simple diagram:

OneWay bindings only propagate changes in the source value to the target (assuming the source implements INotifyPropertyChanged), whereas a TwoWay binding propagates changes in both directions, ensuring that the two values are always synchronized. There are a few other binding modes (OneWayToSource, OneTime…) but one / two way are by far the most commonly used.

WARNING: The default BindingMode for Silverlight is OneWay, whereas in WPF it is BindingMode.Default which means … it depends! From MSDN:

“The default value varies for each dependency property. In general, user-editable control properties, such as those of text boxes and check boxes, default to two-way bindings, whereas most other properties default to one-way bindings.”

This is very confusing if you are writing cross-platform WPF / Silverlight code! In this case I would always recommend specifying the BindingMode explicity.

Summary

So far we have seen what life was like before databinding, where we had to write code to handle changes from both the source and target properties, manually synchronizing the two. With binding, the framework handles this for us, allowing for a more declarative approach to wiring-up our UI to the model that backs it (you do have a model behind your view don’t you?!).

However, you might be wondering why there has been no mention of binding in XAML yet? This was intentional, I wanted to first show how bindings work under-the-hood, introducing the concept of source and target, before leaping into creating them in XAML … which is the subject of the next blog post …

You can download the example code here: BindingExamples.zip

Regards, Colin E.

Visualising StackOverflow Tag Relationships with Silverlight

February 20th, 2012

UPDATE: I have posted the sourcecode for this control on codeproject.

Recently I have been wondering about the wealth of information that can be gleaned from the 2.5 million programming question on Stack Overflow. A few weeks back I found a tag trending tool, which can be used to measure the rise and fall in popularity of tags over time. Whilst this is a great little tool, I am sure there is much more that can be done with the freely available Stack Overflow data, for example, exploring the relationships between the many technologies people ask questions about.

On a recent trip to Copenhagen I decided to put my hours of travelling time to good use and create a Silverlight application that plots the relationships between the various tags. I created an application that downloaded the 1,000 most recent questions via the Stack Overflow API and plotted the relationships between the 20 most popular tags, as seen above.

The graph is constructed as follows:

  • The size of each segment is proportional to the number of questions relating to the tag, i.e. android and java are the most popular tags.
  • Connections between tags indicate questions that have been tagged with both technologies. The thickness of the connection indicates how many questions share these two tags, i.e. jQuery and JavaScript tags appear together quite often.
  • Each segment is coloured based on the number of connections it has, red for many connections, blue for few.

The ordering of segments can be changed using the drop-down control. Probably one of the most interesting views is the one where related tags are clustered. This is done by assigning a ‘weight’ to the current configuration of the graph by summing the length of all connections, with connections that cross the centre of the circle adding most weight. An iterative process is used to minimise the overall graph weight by moving each segment a few steps left and right, until the least ‘weighty’ configuration is found. This is the one where each tag is most closely related to its neighbours.

When clustering is applied we can see small ‘pockets’ of related technologies, with the following patterns emerging

  • The two most popular tags, Java and Android, are very closely related to each other, but have very few other relationships.
  • iOS, Objective-C and iPhone form a close-knit group. However, Objective-C questions are sometimes also tagged with C#, C and C++.
  • C#, .NET and ASP.NET are clustered, however C# has links with many other tags
  • The strongest relationship is between jQuery and JavaScript, probably due to jQuery having become the de-facto framework for JavaScript development, being used on 53% of websites.
  • There is a large cluster of connected web technologies, CSS, HTML, JavaScript, jQuery, reflecting the mix of technologies involved in creating web sites and web applications.
  • Python, whilst being a popular tag, has very few relationships, only being weakly linked to PHP.

I am planning on tidying up the code for this visualisation, making it more generic, allowing it to be used to graph other datasets. Let me know if you are interested in this!

Here is the same graph, but showing the top 30 tags, again, more interesting relationships start to emerge:

Finally, thanks to Chris P., Adrian C. and Graham O. for their ideas and input!

Regards, Colin E.

 

The Gradual Decline in Silverlight Adoption

February 13th, 2012

Around one year ago I made the prediction that Silverlight would have an overall adoption of 81% by the end of 2011. The adoption statistics are now available and indicate that my predictions were wrong by more than 10%, with Silverlight adoption reaching just 67% at the start of this year. So what went wrong?

In my previous blog post I assumed that Silverlight adoption would follow a sigmoid curve as per the Diffusion of Innovation theory. Taking the adoption statistics from StatOwl, I used Excel to fit a logistic function to the data in order to predict the future adoption, arriving at a projected adoption figure of 81% at the end of 2011. However, in my curve fitting it looks like I made one important mistake – I assumed that Silverlight adoption would eventually reach 100%!

By adjusting my Excel spreadsheet to allow a sub-100% adoption I achieved a much better curve fit and the 2011 predictions were reduced from 81% to 75%.

However, data from throughout 2011 seems to indicate that the rate of Silverlight adoption is falling (I think we all know the reason why). Including last years data shows a very good fit to the logistic function, with the rather gloomy outlook that the adoption is asymptotically tending towards 73%.

The graph below shows the adoption statistics reported via StatOwl from 2008 through to 2011, together with my (corrected) predictions based on the data up to 2010, and my predictions based on the complete set of available data.

This doesn’t compare well with flash where the adoption of each new version is faster than the last. With Silverlight adoption statistics tending towards 73% the outlook doesn’t look too great. Is this a technology we should still be investing in?

Personally, I think the answer to this question is “yes” for a couple of reasons:

Whilst the Silverlight plugin might be losing relevance, Windows 8 Metro and Silverlight for Windows Phone 7 are both XAML languages with a similar API. The skills you learn whilst developing Silverlight or WPF applications are certainly going to be relevant in the future.

Businesses have an investment in the skills of their employees, but just as importantly, they invest in the code that they write. Whilst there is some comfort in the ability of their employees to easily adopt new technologies, the cost of migrating a code-base is always going to be much greater. It is clear that Silverlight is no longer going to be the Flash-beating plugin that would be the de-facto choice for interactive content on the web (Flash, and the plugin model in general, is in trouble). However, Silverlight is now a very mature platform that is an appropriate choice for delivery of complex business functionality either within an intranet, where you can control plugin installation, or where the business value of the application being delivered ensures that the 30% without the plugin will install it in order to use your application.

Now, more than ever, is a time for developers to diversify and learn new skills.

Regards, Colin E.

TweetSearch – A Cross platform Metro UI WinRT and Silverlight Application

September 16th, 2011

With the Windows 8 preview release earlier this week, developers are now faced with a whole new and exciting Microsoft stack. The Windows 8 architecture has something of a split-personality, incorporating a completely new runtime, WinRT together with the older Win32 and .NET framework. However, these sit on different sides of a physical divide in both the architecture and the user interface. For more details of this, see my earlier article.

The new WinRT APIs support both C# and XAML, having an interface that is very similar to its .NET counterparts. However, there are a number of differences, most importantly much of the UI now resides in a new namespace. It is clear that transitioning from Silverlight, WP7 or WPF development to using WinRT will be quite easy.

I am sure there exists classes of application that sit best in the Win8 Metro UI, for which you will use WinRT for development. There will also be classes of application that sit best in the Win8 classic desktop, for which you will still be using WPF and Silverlight to develop.

However … there will certainly exist a class of application that sits well in both the Metro and Desktop environment. In the Win8 preview IE does just this.

This introduces a problem, how can we share code between our Silverlight Desktop and WinRT Metro applications?

I have previously presented talks and written articles on cross-platform application development. So I thought I would grab myself a copy of the Win8 preview release and see how easy it is to code-share between a Silverlight and WinRT Metro application.

This blog post describes a simple TwitterSearch application, the Silverlight version is shown below. Simply type in a search string to see the results retrieved from twitter:

A screenshot of the TwitterSearch application built for WinRT Metro is shown below:

When code-sharing between WPF, Silverlight and WP7 applications separation of concerns and solid design patterns are essential in order to navigate the framework differences. For that reason I use the Model-View-ViewModel pattern, this makes it easy to specialise the view for each platform, where they typically differ the most. I will use this same approach for WinRT.

The code is shared between the Silverlight and Win8 Metro application by having two separate solutions which both share files via the Visual Studio file linking feature.

The TwitterSearchViewModel which backs this application simply exposes a search string property and a list of tweets:

public partial class TwitterSearchViewModel : INotifyPropertyChanged
{
  private TweetViewModelCollection _tweets = new TweetViewModelCollection();
 
  private IMarshalInvoke _marshalInvoke;
 
  private string _searchText = "WinRT";
 
  public TwitterSearchViewModel(IMarshalInvoke marshalInvoke)
  {
    _marshalInvoke = marshalInvoke;
  }
 
  /// <summary>
  /// Gets / sets the search term
  /// </summary>
  public string SearchText
  {
    get {  return _searchText;  }
    set
    {
      _searchText = value;
      OnPropertyChanged("SearchText");
    }
  }
 
  /// <summary>
  /// Gets the search results
  /// </summary>
  public TweetViewModelCollection Tweets
  {
    get { return _tweets; }
    set { _tweets = value; }
  }
 
  /// <summary>
  /// Gets a command that executes the search
  /// </summary>
  public ICommand ExecuteSearchCommand
  {
    get
    {
      return new DelegateCommand(() => ExecuteSearch());
    }
  }
}

The IMarshalInvoke interface allows the view model to perform asynchronous calls via the Dispatcher, without being dependant on this UI class, more on this later.

It is here that I hit the first problem, WinRT has ICommand, but it lives in a different namespace! Time to add a WinRT compilation symbol to my WinRT project and throw in a pre-compiler directive:

#if WINRT
 
using Windows.UI.Xaml.Input;
 
#else
 
using System.Windows.Input;
 
#endif

Now my view model compiles just fine. However, when I hooked it up with the view, my bindings were only working in one direction. After appealing to Twitter, the MSDN forums and the WPF Disciples, Laurent Bugnion kindly informed me that WinRT has two different INotifyPropertyChanged interfaces. One within System.ComponentModel and the other in Windows.UI.Xaml.Data, if you use the one from System.ComponentModel it is ignored by the WinRT binding framework. Very confusing!

Fixing this is simply a matter of adding more platform specific namespaces:

#if WINRT
 
// used for ICommand
using Windows.UI.Xaml.Input;
 
// used for INotifyPropertyChanged
using Windows.UI.Xaml.Data;
 
#else
 
using System.ComponentModel;
using System.Windows.Input;
 
#endif

My original code used WebClient, which is not present in WinRT. Fortunately HttpWebRequest is present in both, so I changed my code to use that, hence the need for the IMarshalInvoke interface to marshal execution back onto the UI thread.

As a result, much of the core logic, which makes use of Linq-to-XML, in the view model is shared between both applications:

/// <summary>
/// Parses the response from our twitter request, creating a list of TweetViewModel instances
/// </summary>
private void ParseXMLResponse(string xml)
{
  var doc = XDocument.Parse(xml);
  var items = doc.Descendants(AtomConst.Entry)
                  .Select(entryElement => new TweetViewModel()
                  {
                    Title = entryElement.Descendants(AtomConst.Title).Single().Value,
                    Id = long.Parse(entryElement.Descendants(AtomConst.ID).Single().Value.Split(':')[2]),
                    ProfileImageUrl =  entryElement.Descendants(AtomConst.Link).Skip(1).First().Attribute("href").Value,
                    Timestamp = DateTime.Parse(entryElement.Descendants(AtomConst.Published).Single().Value),
                    Author = entryElement.Descendants(AtomConst.Name).Single().Value
                  });
 
  _tweets.Clear();
  foreach (var item in items)
  {
    _tweets.Add(item);
  }
}
 
/// <summary>
/// Searches for the given term
/// </summary>
private void ExecuteSearch()
{
  IsSearching = true;
 
  // perform the search
  string uri = _twitterUrl + SearchText;
  HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(new Uri(uri));
  request.BeginGetResponse(new AsyncCallback(ReadCallback), request);
}
 
/// <summary>
/// A callback that receives the search results
/// </summary>
private void ReadCallback(IAsyncResult asynchronousResult)
{
  HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
  HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
  using (StreamReader streamReader1 = new StreamReader(response.GetResponseStream()))
  {
    string resultString = streamReader1.ReadToEnd();
 
    // marshall onto the UI thread and parse
    _marshalInvoke.Invoke(() =>
      {
        Tweets.Clear();
        ParseXMLResponse(resultString);
        IsSearching = false;
      });
  }
}

This makes me happy :-)

On a side note, whilst WinRT does not have WebClient, it actually has something much better via classes such as SyndicationFeed which make use of the new C# async and await pattern for dealing with asynchrony. Of course, using these new APIs reduces the amount of code you share with the Silverlight .NET code.

The DelegateCommand implementation again hits the same problem of the same interface being located in a different namespace, yet despite this, most of the code is shared:

#if WINRT
 
// used for ICommand
using Windows.UI.Xaml.Input;
 
#else
 
using System.Windows.Input;
 
#endif
 
namespace SLUGUK.ViewModel
{
  public class DelegateCommand : ICommand
  {
    private Action _action;
 
    public DelegateCommand(Action action)
    {
      _action = action;
    }
 
    public bool CanExecute(object parameter)
    {
      return true;
    }
 
#if WINRT
    public event Windows.UI.Xaml.EventHandler CanExecuteChanged;
#else
    public event EventHandler CanExecuteChanged;
#endif
 
    public void Execute(object parameter)
    {
      _action();
    }
  }
}

Despite the various XAML UI controls being in a different C# namespace, they use the same URIs for their XML namespace mappings. This makes it possible to share XAML as well as C# code between your applications.

However, in much the same way as it makes little sense to share XAML between WP7 and Silverlight due to differences in form-factor and user-experience, I don’t think it makes sense to share XAML between Silverlight and Metro WinRT. The primary focus of the Win8 Metro applications is the touch-first tablet form factor, hence you would expect it to be quite different from a desktop application.

The following is the XAML for my Metro UI application:

<UserControl x:Class="WinRTMetroTwitter.View.TwitterSearchView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="using:WinRTMetroTwitter.View"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">
 
    <UserControl.Resources>
        <local:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
        <local:ImageConverter x:Key="ImageConverter"/>        
    </UserControl.Resources>
 
    <Grid x:Name="LayoutRoot" Background="#FF0C0C0C">
        <Grid Margin="50"
              Width="400"
              HorizontalAlignment="Left">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <StackPanel Orientation="Horizontal">
                <TextBox Text="{Binding Path=SearchText, Mode=TwoWay}"
                     Width="200"/>
                <Button Command="{Binding Path=ExecuteSearchCommand}"
                    Content="Go!"/>
                <TextBlock VerticalAlignment="Center"
                     Visibility="{Binding Path=IsSearching, Converter={StaticResource BoolToVisibilityConverter}}"
                     Text="Searching ..."
                     Margin="20,0,0,0"
                     FontSize="15"/>
            </StackPanel>
 
            <!-- renders the search results -->
            <ItemsControl x:Name="itemsControl"
                          Grid.Row="2">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <StackPanel Orientation="Vertical"/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal"
                                    Margin="5">
                           <Image Source="{Binding ProfileImageUrl, Converter={StaticResource ImageConverter}}"
                                  Width="96" Height="96"
                                  Stretch="UniformToFill"
                                  Margin="2"
                                  VerticalAlignment="Top"/>
 
                            <StackPanel Orientation="Vertical">
                                <TextBlock Text="{Binding Title}"
                                           TextWrapping="Wrap"
                                           FontSize="15"
                                           Width="300"
                                           HorizontalAlignment="Left"/>
                                <StackPanel Orientation="Horizontal">
 
                                    <TextBlock FontWeight="Bold"
                                               Text="{Binding Path=Author}"
                                               FontSize="15"/>
 
                                    <TextBlock Margin="10,0,0,0"
                                              Text="{Binding Path=Timestamp}"
                                               FontSize="15"
                                              Foreground="#333"/>
                                </StackPanel>
                            </StackPanel>
                        </StackPanel>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
 
            <Rectangle Fill="#FF0C0C0C"
                   Opacity="0.5"
                   Grid.Row="1"
                   Visibility="{Binding Path=IsSearching, Converter={StaticResource BoolToVisibilityConverter}}"/>
        </Grid>
    </Grid>
</UserControl>

If you are a Silverlight developer you will notice that everything here is standard Silverlight, it is just wired-up to different classes via the XAML namespace mappings.

I did discover that the IValueConverter signature within WinRT is a bit different. Within this application, the value conversion logic is so simple it is hardly worth code-sharing, however, it would be a very simple exercise if you wished to do so.

namespace WinRTMetroTwitter.View
{
  public class BoolToVisibilityConverter : IValueConverter
  {
    public object Convert(object value, string typeName, object parameter, string language)
    {
      return (bool)value ? Visibility.Visible : Visibility.Collapsed;
    }
 
    public object ConvertBack(object value, string typeName, object parameter, string language)
    {
      throw new NotImplementedException();
    }
  }
}

Finally, I did hit against one further problem. With WinRT it seems that there is a currently a bug which prevents ItemsControl binding to collections via INotifyCollectionChanged from working. This has been raised in the MSDN forums and I am sure it will be fixed. As a simple workaround I added the following code-behind (gasp!):

public sealed partial class TwitterSearchView : UserControl
{
  private TwitterSearchViewModel feedViewModel;
 
  public TwitterSearchView()
  {
    InitializeComponent();
 
    this.Loaded += ResultsView_Loaded;
  }
 
  private void ResultsView_Loaded(object sender, RoutedEventArgs e)
  { 
    feedViewModel = this.DataContext as TwitterSearchViewModel;
 
    // detect collection changed
    feedViewModel.Tweets.CollectionChanged += FeedItems_CollectionChanged;
  }
 
 
  private void FeedItems_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
  {
    // manually 'refresh' the UI
    itemsControl.ItemsSource = null;
    itemsControl.ItemsSource = feedViewModel.Tweets;
  }
}

Conclusions

Creating a cross-platform WinRT / Silverlight application is entirely possible, using the same techniques that we currently employ for cross-platform Silverlight / WPF / WP7 applications. There are further complications relating to classes living in different namespaces and there will of course be other detail-level differences that this simple example does not touch upon. However, I think this presents a feasible and promising route for re-using existing Silverlight/ WPF code, and for developing applications that target the Win8 tablet, WP7 phone and Silverlight (or WPF) desktop with a single code-base.

You can download the full sourcecode: CrossPlatformTwitter.zip

Regards, Colin E.