XAML – How to know when a VisualState Transition is completed in a CustomControl

I’ve been developing for WinRT for quiet some time now in XAML and C#. I’ve faced an issue where I needed to wait that an animation was completed before starting a piece of work in a view model. The problem was that this animation was a VisualState transition inside one of my custom controls.

My custom control represents a reversi token which has two sides, black and white. When its IsBlack property changes it triggers a visual state transition. As my application uses the MVVM pattern I needed to find a way to propagate the information that an animation has started and stopped from the custom control to the view model.

I first created added a property to my Token control :

public bool IsColourChanging
{
    get { return (bool) GetValue(IsColourChangingProperty); }
    set { SetValue(IsColourChangingProperty, value); }
}

public static readonly DependencyProperty IsColourChangingProperty =
    DependencyProperty.Register("IsColourChanging", typeof (bool), typeof(Token), new PropertyMetadata(false));

Then in the OnApplyTemplate method of the control I call the following method which is used to subscribed to the CurrentStateChanging and CurrentStateChanged events of the VisualStateGroup containing the states representing each colour :

private void HandleColourChanging()
{
    var child = VisualTreeHelper.GetChild(this, 0) as FrameworkElement;

    Debug.Assert(child != null, "Token's template must be defined !");

    var groups = VisualStateManager.GetVisualStateGroups(child);

    Debug.Assert(groups != null, "Token's VisualStateGroups should be defined!");

    // The Cast operator is not necessary in Windows 8 Metro Style Apps
    var colourGroup = groups.Cast<VisualStateGroup>().FirstOrDefault(g => g.Name == ColourStatesGroupName);

    Debug.Assert(colourGroup != null, "Token's VisualState Transition should be defined!");

    colourGroup.CurrentStateChanging += ColourGroupCurrentStateChanging;
    colourGroup.CurrentStateChanged += ColourGroupCurrentStateChanged;
}

In the ColourGroupCurrentStateChang[ing/ed] methods I now just have to set the IsColourChanging property accordingly :

private void ColourGroupCurrentStateChanging(object sender, VisualStateChangedEventArgs e)
{
    IsColourChanging = true;
}

private void ColourGroupCurrentStateChanged(object sender, VisualStateChangedEventArgs e)
{
    IsColourChanging = false;
}

 

At this step, every time a transition between two colours is run, the IsColourChanging is set to true until the transition complete.

So now how to propagate this information to my view models ? Using bindings of course and here’s how it can be done assuming the ItemsControl ItemsSource property is set to a collection of TokenViewModels :

<ItemsControl>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <local:Token IsBlack="{Binding IsBlack}"
                            IsColourChanging="{Binding IsAnimating, Mode=TwoWay}"
                            Width="100"
                            Height="100" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

You can see here that the IsColourChanging property of the control is bound to the IsAnimating control of its view model in a two way manner. Now it’s up to to viewmodel to react to the change of the IsAnimating property as wanted.

I consider this trick to be important as WinRT application are made to be fast and fluid and so using a lot a animations. As fast and fluid does not mean unmaintainable it’s a way among others to separate your logic between the view and the view model.

You can see a sample code in WPF in my skydrive as usual.

Hope it’ll help.

Back to Basics – C# – Casting an integer into an enumeration

Recently I encountered a cast that I found interesting. It was trying to convert an integer into an enumeration in a way I never met before.

Let’s take this enumeration type :

public enum MyEnum
{
    Zero = 0,
    One = 1
}

And the following cast :

MyEnum res;
int val = 1;

res = (MyEnum)Enum.Parse(typeof(MyEnum), val.ToString());

My first reaction was to wonder why converting an integer into a string to cast it into an enumeration just after when a simple direct cast is enough ?

res = (MyEnum)val;

I ask a workmate If I didn’t miss a thing and I was answered that Enum.Parse throws an exception if the val variable has a value that doesn’t fit in the enumeration (for example 2).

As I was not totally convinced I decided to create a little test :

// Cast 1
res = (MyEnum)Enum.ToObject(typeof(MyEnum), val);
Console.Out.WriteLine("{0}", res);

// Cast 2
res = (MyEnum)Enum.Parse(typeof(MyEnum), val.ToString(CultureInfo.InvariantCulture));
Console.Out.WriteLine("{0}", res);

// Cast 3
res = (MyEnum)val;
Console.Out.WriteLine("{0}", res);

With all of these tests I realized all the casts were working with a value of 2. No exception thrown. This means that the numerical value of res is 2 when the maximum value of the enumeration is 1 ! This feels like C.

Now what happens with the following test:

// Cast 4
string sVal = "Two";
res = (MyEnum)Enum.Parse(typeof(MyEnum), sVal);
Console.Out.WriteLine("{0}", res);

This time we have got an exception indicating that the value “Two” doesn’t exist in the enumeration, which is an expected behavior.

If we go back to the code that troubled me at the beginning of this post we realize the developer error was to think that Enum.Parse works the same way with strings than with strings containing an integer.

 

Therefore how can we be sure that the value we want to convert exists in the enumeration ?

We have many choices :

if (typeof(MyEnum).IsEnumDefined(val))
{
    res = (MyEnum)val;
    Console.Out.WriteLine("{0}", res);
}
else
    Console.Out.WriteLine("Cannot convert {0} to MyEnum", val);

if (Enum.IsDefined(typeof(MyEnum), val))
{
    res = (MyEnum) val;
    Console.Out.WriteLine("{0}", res);
}
else
    Console.Out.WriteLine("Cannot convert {0} to MyEnum", val);

The first method only exists starting .NET 4 whereas the second exists in the previous framework versions too.

 

We learn everyday our favorite language :-)

Did you expect such a behavior ?

Asynchronism – Faking latency

One recurring problem when we create an application using asynchronous calls is to test this asynchronism. We want to verify the behavior of our application if an operation take 10 seconds or 1 minute to complete.

Let’s take a simple exemple.

We have the MyAsyncMethod method which notifies the end of its execution by raising then MyAsyncMethodCompleted event. We want to simulate a 5 second latency on this method.

Here’s the code allowing us to do that :

public void MyAsyncMethod()
{
    Timer timer = null;

    var context = SynchronizationContext.Current;

    TimerCallback c = state =>
    {
        if (timer != null)
            timer.Dispose();

        context.Post(o => MyAsyncMethodCompleted(this, null));
    };
    timer = new Timer(c, null, 5000, int.MaxValue);
}

The idea is to create a time that will be waiting 5 seconds to invoke a callback. This callback will dispose the timer and invoke the completed event. The main issue here is that the timer will invoke its callback in another thread than the one which initiated the call. In order to call back on the right thread we saved the synchronisation context in a variable. Then, we post the call of the completed event to the synchronisation context. This is like the Dispatcher.BeginInvoke for Silverlight or WPF but here it works for any threads.

So in the end, for the calling method everything is transparent and we introduced latency.

Simple and useful :-)

Using NetTcpBinding in Silverlight with IIS

 

In this post, I will extend the push temperature project to add a netTcpBinding endpoint to the wcf service and use it in Silverlight.

 

Configuring the web server

This is probably the most annoying part of this article, but be sure to make no mistakes here or you’ll have some surprises. I had some myself.

Note that you need to run IIS to use the WCF NetTcp binding as the baked Visual Studio Web Server doesn’t support it.

1 – Add Non-HTTP WCF Activation

First add the windows feature as in the following screenshot :

nonhttpwcfactivation

After the installation is complete check that the Net.Tcp Listener Adapter is started :

nettcplisteneradapterservice

2 – Host the website in IIS

First, you need to run Visual Studio as administrator in order to let him modify your local IIS instance. For this article I use the exact same project as the previous article.

In the properties of the web project I instruct Visual Studio that I want to deploy on the local IIS server (don’t forget to press the Create Virtual Directory button).

vswebappproperties

3 – Configure bindings and protocols

Open the IIS Manager and look for the website hosting your web application (usually Default Web Site).

Add the net.tcp binding on the port 4502. This is the port we will use in our Silverlight application (Silverlight untrusted in-browser applications are limited to ports 4502 to 4534).

addnettcpbindingiis

You also need to add NetTcp to the list of the enabled protocols for your web application. For this selected your web application and in the advanced properties, add the net.tcp protocol as in the following screenshot :

addnettcpprotocoliis

The final step in the configuration consists in setting up IIS with .NET 4. In order to do this, open a Visual Studio Command Prompt as an administrator and run the following command line :

aspnet_regiis.exe –iru

 

Configuring the WCF Services

Now that IIS is configured correctly, we need to configure the WCF services.

I’ll just copy my configuration file that allows both netTcp and pollingDuplex at the same time. Note that korell is my machine’s name and you’ll need to put yours instead of course.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.web>
        <compilation debug="true" targetFramework="4.0" />
    </system.web>

    <system.serviceModel>
      <extensions>
        <bindingExtensions>
          <add name="pollingDuplexHttpBinding" type="System.ServiceModel.Configuration.PollingDuplexHttpBindingCollectionElement, System.ServiceModel.PollingDuplex, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
        </bindingExtensions>
      </extensions>
      <bindings>
        <pollingDuplexHttpBinding>
          <binding name="multipleMessagesPerPollPollingDuplexHttpBinding" duplexMode="MultipleMessagesPerPoll" maxOutputDelay="00:00:00.500" sendTimeout="00:00:02.000" closeTimeout="00:00:02.000" />
        </pollingDuplexHttpBinding>

        <netTcpBinding>
          <binding name="netTcpBindingConfig">
            <security mode="None" />
          </binding>
        </netTcpBinding>

      </bindings>
      <services>
        <service name="SilverlightReactivePushServer.Web.TemperatureService">
          <endpoint address="wsDualHttp" binding="wsDualHttpBinding" contract="SilverlightReactivePushServer.Web.ITemperatureService" />
          <endpoint address="polling" binding="pollingDuplexHttpBinding" bindingConfiguration="multipleMessagesPerPollPollingDuplexHttpBinding" name="pollingDuplex" contract="SilverlightReactivePushServer.Web.ITemperatureService" />
          <endpoint address="netTcp" binding="netTcpBinding" bindingConfiguration="netTcpBindingConfig" contract="SilverlightReactivePushServer.Web.ITemperatureService" />
          <endpoint address="mex" binding="mexHttpBinding" name="mex" contract="IMetadataExchange" />
          <host>
          <baseAddresses>
            <add baseAddress="net.tcp://korell:4502/SilverlightReactivePushServer.Web/TemperatureService.svc" />
            <add baseAddress="http://korell/SilverlightReactivePushServer.Web/TemperatureService.svc" />
          </baseAddresses>
          </host>
        </service>
      </services>
        <behaviors>
            <serviceBehaviors>
                <behavior name="">
                  <serviceMetadata httpGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="true" />
                </behavior>
            </serviceBehaviors>
        </behaviors>

      <serviceHostingEnvironment multipleSiteBindingsEnabled="false" aspNetCompatibilityEnabled="true" />
    </system.serviceModel>
</configuration>

We also need to add the following clientaccesspolicy file at the root of the website (here it’s Default Web Site) :

<?xml version="1.0" encoding="utf-8"?>
<access-policy>
  <cross-domain-access>
    <policy>
      <allow-from http-request-headers="*">
        <domain uri="*" />
      </allow-from>
      <grant-to>
        <resource path="/" include-subpaths="true" />
        <socket-resource port="4502-4530" protocol="tcp" />
      </grant-to>
    </policy>
  </cross-domain-access>
</access-policy>

Note that this file is really permissive and should be used in developement environments only.

Modifying the Silverlight client

In the Silverlight client we first need to add a reference to System.ServiceModel.NetTcp as in the following screenshot :

sladdreferencenettcp

After this we need to modify the ServiceClient.config file to add the netTcp endpoint :

<configuration>
  <system.serviceModel>
    <bindings>
      <customBinding>
        <binding name="httpPolling">
          <binaryMessageEncoding />
          <pollingDuplex duplexMode="MultipleMessagesPerPoll" />
          <httpTransport transferMode="StreamedResponse" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
        </binding>
        <binding name="NetTcpBinding_ITemperatureService">
          <binaryMessageEncoding />
          <tcpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
        </binding>
      </customBinding>
    </bindings>
    <client>
      <endpoint address="http://korell/SilverlightReactivePushServer.Web/TemperatureService.svc/polling"
                binding="customBinding"
                bindingConfiguration="httpPolling"
                contract="TemperatureServer.ITemperatureService"
                name="HttpPollingDuplexBinding_ITemperatureService"/>
      <endpoint address="net.tcp://korell:4502/SilverlightReactivePushServer.Web/TemperatureService.svc/netTcp"
          binding="customBinding" bindingConfiguration="NetTcpBinding_ITemperatureService"
          contract="TemperatureServer.ITemperatureService" name="NetTcpBinding_ITemperatureService" />
    </client>
  </system.serviceModel>
</configuration>

You’ll notice that we now have two bindings :

  • NetTcpBinding_ITemperatureService
  • HttpPollingDuplexBinding_ITemperatureService

We can choose which one will be used in the constructor of the service client’s instance :

_client = new TemperatureServiceClient("HttpPollingDuplexBinding_ITemperatureService");
// OR
_client = new TemperatureServiceClient("NetTcpBinding_ITemperatureService");

And that’s pretty much it. The proxy class used for each binding is the same so there’s no need to change anything else. Just choose your binding and run with it.

I’ve created a sample project that can change its binding at runtime.

You can see it in action there : http://grogru.com/slduplex

I have no other way to prove it work than telling you to analyse your network traffic using a tool like Microsoft Network Monitor.

You can find the source code of this sample on my skydrive as always.

Hope you’ll like it Clignement d'œil

Using reactive extensions for a push-based client-server communication with Silverlight and WCF

In the previous article, I explained you how Rx can improve the process of downloading data from a WCF service. This was a classical scenario where the Silverlight client explicitly asks for data from the server.

Now we will see how we can use Rx in a push based scenario where the server sends data to the Silverlight client without any explicit demand from it.

 

0 – The prerequisites

In order to follow this article you need to make sure you have the latest version of Rx and the Silverlight SDK. At the time theses lines were written I was using Silverlight 4.0.60310.0 and Rx 1.0.10621.0.

1 – The context

We want to create a Silverlight application and a WCF service that pushes temperature data in the Celsius scale to the client at random intervals. The Silverlight application (aka client) has two independent modules, one for displaying the temperature received in the Celsius scale and the other one to display it in the Fahrenheit scale. Even though we have two independent modules, we want them to use the same connection to the WCF service to receive the temperature. The module will also have no direct reference on the WCF service proxy allowing us to use dependency injection and unit testing of the modules’ view models.

2 – Duplex service

A duplex service is a service where both the client and the server can send data through the same connection which is exactly what we want here. We chose to create a service using the Subscribe-Publish pattern. The client will create a connection to the server using a Subscribe method and then wait asynchronously for data from it.

In WCF, this kind of scenario is made possible by using a service callback. This callback is an interface defined in the server side and implemented at the client’s side which the server will use whenever it wants to send data to the client.

In order to use these callbacks we need to choose a compatible WCF binding. When creating a WPF application we can use all the bindings provided by default such as wsDualHttpBinding but in Silverlight we are somewhat restricted. In Silverlight we can use netTcpBinding or pollingDuplexHttpBinding. The first one is a little bit harder to configure than the second one and I will write about it in another post. For today, I’ll focus on the second one.

3 – PollingHttpDuplexBinding

This binding is a little bit special because it’s a duplex binding over an http communication. As it is well-known, http is not a duplex communication protocol. In http the client has to explicitly ask the server for data. When we need to have such a duplex communication using Silverlight we can implement a custom polling code. Polling is the process where the client regularly asks the server whether some new data is available or not. The pollingHttpDuplexBinding already implements the polling code for us directly inside the communication layer improving the performance of the overall process.

The pollingHttpDuplexBinding is not included by default in Silverlight or WCF. We can find the assemblies for the client and the server in the Silverlight SDK. On my hard drive theses dlls are located in the C:\Program Files (x86)\Microsoft SDKs\Silverlight\v4.0\Libraries folder so for you it should be there C:\[ProgramFilesArchitecture]\Microsoft SDKs\Silverlight\[SilverlightVersion]\Libraries.

There is two assemblies required for this binding to work, one for the client and the other one for the server.

In the web project hosting the Silverlight application we add a reference to the server’s System.ServiceModel.PollingDuplex.dll and in the Silverlight client we add a reference to client’s System.ServiceModel.PollingDuplex.dll.

4 – Creating the service

In the web project we first create two interfaces defining the WCF contracts for both the service and it’s service callback.

[ServiceContract(CallbackContract = typeof(ITemperatureServiceCallback))]
public interface ITemperatureService {
    [OperationContract(IsOneWay = true)]
    void Subscribe();

    [OperationContract(IsOneWay = true)]
    void Unsubscribe();
}

 

public interface ITemperatureServiceCallback {
    [OperationContract(IsOneWay = true)]
    void PushTemperature(double temperature);
}

 

Then we can create an implementation of the service (this implementation is a simple one that would not suit for production needs). This implementation creates a timer that will call the service callback of each clients connected to the services to send new random temperature data.

public class TemperatureService : ITemperatureService {
    private static readonly object _locker = new object();
    private static readonly List<OperationContext> _clients = new List<OperationContext>();
    private static readonly Random _random = new Random();

    private static Timer _updateTimer;

    static TemperatureService()
    {
        _updateTimer = null;
    }

    public void Subscribe()
    {
        if (_clients.Contains(OperationContext.Current) == false)
        {
            lock (_locker)
            {
                if (_clients.Count == 0)
                    _updateTimer = new Timer(TimerTick, null, 500, 2000);

                _clients.Add(OperationContext.Current);
            }
        }
    }

    public void Unsubscribe()
    {
        RemoveClient(OperationContext.Current);
    }

    private static void TimerTick(object state)
    {
        Task.Factory.StartNew(() =>
        {
            double temperature = _random.Next(-200, 400) * 0.1d;

            // Copy the clients array because it can be modified while been read var clients = _clients.ToArray();
            foreach (var client in clients)
            {
                try {
                    var channelState = client.Channel.State;
                    if (channelState == CommunicationState.Opened)
                    {
                        var callbackChannel = client.GetCallbackChannel<ITemperatureServiceCallback>();
                        callbackChannel.PushTemperature(temperature);
                    }
                    else {
                        RemoveClient(client);
                    }
                }
                catch (TimeoutException)
                {
                    RemoveClient(client);
                }
                catch (Exception)
                {
                    _updateTimer.Dispose();
                }
            }
        });
    }

    private static void RemoveClient(OperationContext client)
    {
        lock (_locker)
        {
            _clients.Remove(client);
        }
    }
}

In this implementation you have to focus on two things :

  • OperationContext.Current
  • client.GetCallbackChannel<ITemperatureServiceCallback>

OperationContext.Current gives us information about the client that has called the current executing service method.

client.GetCallbackChannel gives us an instance of the service callback to use in order to send data from the server to the client.

 

Then we expose our service using a .svc file. In my example the svc file looks like this :

<%@ ServiceHost Language="C#" Debug="true" Service="SilverlightReactivePushServer.Web.TemperatureService" CodeBehind="TemperatureService.svc.cs" %> 

 

Finally we need to configure the binding in the web.config file, here’s how the serviceModel section is looking :

<system.serviceModel>
  <extensions>
    <bindingExtensions>
      <add name="pollingDuplexHttpBinding"
            type="System.ServiceModel.Configuration.PollingDuplexHttpBindingCollectionElement, System.ServiceModel.PollingDuplex, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
    </bindingExtensions>
  </extensions>
  <bindings>
    <pollingDuplexHttpBinding>
      <binding name="multipleMessagesPerPollPollingDuplexHttpBinding"
                duplexMode="MultipleMessagesPerPoll"
                maxOutputDelay="00:00:00.500"
                sendTimeout="00:00:02.000"
                closeTimeout="00:00:02.000"/>
    </pollingDuplexHttpBinding>
  </bindings>
  <services>
    <service name="SilverlightReactivePushServer.Web.TemperatureService">
      <endpoint address="" binding="pollingDuplexHttpBinding"
      bindingConfiguration="multipleMessagesPerPollPollingDuplexHttpBinding"
              name="pollingDuplex"
              contract="SilverlightReactivePushServer.Web.ITemperatureService" />
      <endpoint address="mex" binding="mexHttpBinding" name="mex" contract="IMetadataExchange" />
    </service>
  </services>
    <behaviors>
        <serviceBehaviors>
            <behavior name="">
                <serviceMetadata httpGetEnabled="true" />
                <serviceDebug includeExceptionDetailInFaults="false" />
            </behavior>
        </serviceBehaviors>
    </behaviors>

  <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>

We’re now done for the server side.

5 – Using the service in Silverlight

First let’s add a reference to our previously defined service and let’s define it’s namespace as TemperatureServer.

The tool used by Visual Studio to generate the service proxy correctly generates the needed classes but doesn’t generate a proper ServiceReferences.ClientConfig file. By not proper I just mean empty.

So let’s configure the reference by ourselves (don’t forget to replace the endpoint addresses by yours).

<configuration>
  <system.serviceModel>
    <bindings>
      <customBinding>
        <binding name="httpPolling">
          <binaryMessageEncoding />
          <pollingDuplex duplexMode="MultipleMessagesPerPoll" />
          <httpTransport transferMode="StreamedResponse" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
        </binding>
      </customBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost:1614/TemperatureService.svc"
                binding="customBinding"
                bindingConfiguration="httpPolling"
                contract="TemperatureServer.ITemperatureService" />
    </client>
  </system.serviceModel>
</configuration>

We will now create a TemperatureService class that will wrap the WCF service proxy as an observable service. This class is a singleton (be free to use any dependency injection libraries instead of a singleton) that will be used into every modules (Celsius and Fahrenheit) to call the web service. Here’s how it looks like :

public class TemperatureService {
    private static readonly TemperatureService _temperature = new TemperatureService();

    private TemperatureServiceClient _client;
    private readonly IObservable<double> _temperatures; 

    protected TemperatureService()
    {
        _temperatures = Observable.Create<double>(observer =>
        {
            if (_client == null)
            {
                _client = new TemperatureServiceClient();
                _client.SubscribeAsync();
            }

            _client.PushTemperatureReceived += (s, a) => observer.OnNext(a.temperature);

            return () => { };
        });
    }

    public IObservable<double> Temperatures
    {
        get { return _temperatures; }
    }

    public static TemperatureService Current
    {
        get { return _temperature; }
    }
}

In the constructor we create an observable that will call the SubscribeAsync method of our WCF service once. Then, every time our observable of temperatures is subscribed to, we register to the PushTemperatureReceived event of the WCF proxy class. The lambda we use here to register to the event just pushes the temperature received into the observable by using the OnNext method of its observer. And that pretty much it, all the magic happens here. Now every time we received a temperature from the server, it will be available to all the subscribers of the observable.

 

I created two views for displaying the temperatures in Celcius and Farenheit. Here’s their XAML code :

<UserControl x:Class="SilverlightReactivePushServer.Views.CelsiusView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding CelsiusTemperature}" />
        <TextBlock Text=" °C" />
    </StackPanel>
</UserControl>

<UserControl x:Class="SilverlightReactivePushServer.Views.FahrenheitView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding FahrenheitTemperature}" />
        <TextBlock Text=" °F" />
    </StackPanel>
</UserControl>


Here’s how I used it in the main view :

<UserControl x:Class="SilverlightReactivePushServer.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:views="clr-namespace:SilverlightReactivePushServer.Views">

    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <views:CelsiusView Grid.Column="0" HorizontalAlignment="Right" Margin="5" />
        <views:FahrenheitView Grid.Column="1" HorizontalAlignment="Left" Margin="5" />
    </Grid>
</UserControl>


Each of the temperature views has it’s own view model. Here’s their implementation :

 

public class CelsiusViewModel : INotifyPropertyChanged {
    private double _celsiusTemperature;
    public event PropertyChangedEventHandler PropertyChanged;

    public double CelsiusTemperature
    {
        get { return _celsiusTemperature; }
        private set {
            if (_celsiusTemperature != value)
            {
                _celsiusTemperature = value;
                RaisePropertyChanged("CelsiusTemperature");
            }
        }
    }

    public CelsiusViewModel()
    {
        TemperatureService.Current.Temperatures.Subscribe(t => CelsiusTemperature = t);
    }

    private void RaisePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

 

public class FahrenheitViewModel : INotifyPropertyChanged {
    private double _fahrenheitTemperature;

    public event PropertyChangedEventHandler PropertyChanged;

    public double FahrenheitTemperature
    {
        get { return _fahrenheitTemperature; }
        private set {
            if (_fahrenheitTemperature != value)
            {
                _fahrenheitTemperature = value;
                RaisePropertyChanged("FahrenheitTemperature");
            }
        }
    }

    public FahrenheitViewModel()
    {
        TemperatureService.Current.Temperatures.Subscribe(t => FahrenheitTemperature = (9 / 5) * t + 32);
    }

    private void RaisePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

That’s pretty much it. Everything already works fine with that. Each of the view models subscribe to the Temperatures observable defined in the TemperatureService class we created earlier and just refreshes their own temperature property with some conversion calculation for the Fahrenheit view model.

 

6 -  Conclusion

We have now a duplex service used by Silverlight that will work over the classical http protocol. We use the reactive extensions to simplify our code and to share the same network resources across different view models that needed the same information at the same time.

I find it pretty sexy and you ?

 

As usual you can find the code used in the example in my skydrive.

Hope you liked it.

Reactive Extensions – Simple asynchronous repository

In Silverlight, all webservices calls are asynchronous. Therefore, when implementing a repository in Silverlight we have to do things a little bit differently as we would have done in Asp.Net or WPF.

Let’s take an example. We have a website exposing a list of customers through a WCF service. We want our Silverlight application to list all these customers inside a ListBox. The service can return tenth of thousands of customers. Because of that we cannot retrieve all of them within a single call.

Let’s see the definition of the Service :

[ServiceContract(Name = "CustomerService")]
public interface ICustomerService {
    [OperationContract]
    int Count();

    [OperationContract]
    IEnumerable<Customer> Get(int start, int count);
}

We can see that to retrieve all the customers, we first have to know how many there are using the Count method and then call the Get method to retrieve a certain number of them.

Let’s see how a traditional asynchronous implementation of a repository using this service could look like :

public class CustomerAsyncRepository {
    public void GetAll(Action<IEnumerable<Customer>> callback)
    {
        var list = new List<Customer>();
        var client = new CustomerServiceClient();
        client.CountCompleted +=
            (sender, e) =>
            {
                if (e.Result > 1000)
                {
                    var state = new GetState { Count = e.Result, Offset = 0, Step = 500 };
                    ((CustomerServiceClient)sender).GetAsync(state.Offset, state.Step, state);
                }
                else ((CustomerServiceClient)sender).GetAsync(0, e.Result);
            };

        client.GetCompleted += (sender, e) =>
        {
            list.AddRange(e.Result);

            var state = e.UserState as GetState;

            if (state != null && state.Offset + state.Step < state.Count)
            {
                state.Offset += state.Step;
                ((CustomerServiceClient)sender).GetAsync(state.Offset, state.Step, state);
            }
            else {
                ((CustomerServiceClient)sender).CloseAsync();
                callback(list);
            }
        };

        client.CountAsync();
    }

    private class GetState {
        public int Offset { get; set; }
        public int Step { get; set; }
        public int Count { get; set; }
    }
}

The GetAll method takes a callback as parameter which we will call when all the customers have been retrieved. This callback will be called with the list of all the customers retrieved, it’s then up to the caller to do whatever necessary (here setting the ItemsSource of a listbox to the list of customers). It also checks the number of customers to retrieve and if there’s more than a thousand, it switches into a mode where it gets all the customers by group of 500 and by calling the service as many times as necessary. To be able to do that, we created the GetState class that represents the current state of the multiple service calls operation.

Here is how the GetAll method is called and its return used :

var repository = new CustomerAsyncRepository();
repository.GetAll(customers => lstBox.ItemsSource = new ObservableCollection<Customer>(customers));

While this technique works great and is completely asynchronous, it has some flaws. The main issue here is that we have to wait until we get all the customers to invoke the callback, and it could last for a minute or more. Even if we have already retrieved half of the customers, the user would not know it and would wait. To give the user a chance to work with the set of data already loaded, we could invoke the callback for every call of the webservice but we would then face the problem that the caller of the GetAll method would not know when all the customers have been retrieved. There’s still some ways to work around this but I’ll stop here and start to make things clean by using Rx.

With Rx, instead of having a callback as a parameter, the GetAll method would just return an IObservable of Customer. This IObservable represents an asynchronous collection of elements where the data is pushed to us instead of being pulled like with IEnumerable (this is called the duality between IEnumerable and IObservable). Furthermore, IObservable provides a way to know when all elements have been retrieved which is perfect for us.

After a little bit of refactoring the repository would look like this :

public class CustomerReactiveRepository {
    public IObservable<Customer> GetAll()
    {
        return Observable.Create<Customer>(observer => OnSubscribe(observer));
    }

    private static Action OnSubscribe(IObserver<Customer> observer)
    {
        try {
            var client = new CustomerServiceClient();
            client.CountCompleted += (sender, e) =>
            {
                if (e.Result > 1000)
                {
                    var state = new GetState { Count = e.Result, Offset = 0, Step = 500 };
                    ((CustomerServiceClient)sender).GetAsync(state.Offset, state.Step, state);
                }
                else ((CustomerServiceClient)sender).GetAsync(0, e.Result);
            };

            client.GetCompleted += (sender, e) =>
            {
                foreach (var c in e.Result)
                    observer.OnNext(c);

                var state = e.UserState as GetState;

                if (state != null && state.Offset + state.Step < state.Count)
                {
                    state.Offset += state.Step;
                    ((CustomerServiceClient)sender).GetAsync(state.Offset, state.Step,
                                                                state);
                }
                else {
                    ((CustomerServiceClient)sender).CloseAsync();
                    observer.OnCompleted();
                }
            };

            client.CountAsync();
        }
        catch (Exception e)
        {
            observer.OnError(e);
        }

        return () => { };
    }

    private class GetState {
        public int Offset { get; set; }
        public int Step { get; set; }
        public int Count { get; set; }
    }
}

Most of the code here remains unchanged, only the signature of the method and the way the customers are returned really changes. The GetAll method now returns an IObservable of Customers by using the Observable.Create method. This method takes into parameter a delegate to the method to invoke when the observable will be subscribed to passing an IObserver of customer. The IObserver is for IObservable what IEnumerator is for IEnumerable.

IObserver provides three important methods :

  • OnNext (the method to invoke when we want to push a new item into the observable)
  • OnCompleted (the method to invoke when all the elements have be pushed, this terminates the observable)
  • OnError (the method to invoke when the process of getting all the elements encountered an error, this terminates the observable)

Whenever we receive new customers, we just push them into the observable and they become immediately available to the subscriber.

The OnSubscribe method returns a delegate to the method to invoke to free all the ressources used by the process. This method is invoked when the observable is terminated. Here we don’t have anything to free so we just return an empty method.

So now let’s see how this repository is used :

var customers = new ObservableCollection<Customer>();
lstBox.ItemsSource = customers;
var repository = new CustomerReactiveRepository();
repository.GetAll().Subscribe(customers.Add);

We create an ObservableCollection as before and use it as the ItemsSource of Listbox. We then subscribe to the observable returned by the GetAll method passing it a delegate to the Add method of the previously declared ObservableCollection.

Doing so, the listbox will be populated as new items become available, making the user experience much better.

By using Rx, we also have access to its Linq operators allowing us to easily put more controls to our collection. For exemple, we could easily tell Rx to execute the get operation in the threadpool’s thread and to give us the results back to the dispatcher thread like this :

repository.GetAll()
    .ObserveOn(new DispatcherSynchronizationContext())
    .SubscribeOn(Scheduler.ThreadPool)
    .Subscribe(customers.Add);

I invite you to download the sources used to write this article on my skydrive, so you can better understand how it improves both the code and the user experience.

nRoute – RelayConverters – Creation of local converters

When developing Silverlight or WPF application we sometimes need de create converters that would be useful only in a particular view. We must then create
a class and its corresponding file that will be completely useless for the rest
of the application. On big projects it would lead to a huge number of
converters.

The previous article was about RelayCommands, now we will see how nRoute
helps in solving our problem by using RelayConverters.

RelayConverters follow the same principle as RelayCommands with a declaration
of a relay in resource and an initialization done with a behavior. Enough talks,
let’s code.

We will use a slightly modified version of the view models defined on the
article about RelayCommands.

public class Book
{
    public long ID { get; set; }
    public string Author { get; set; }
    public string Title { get; set; }
    public int Likes { get; set; }
}
public class MainPageViewModel : ViewModelBase
{
    private readonly IEnumerable<Book> _books;

    public MainPageViewModel()
    {
        var authors = new[] {
            "Terry Pratchett",
            "Molière",
            "Shakespeare",
            "Frank Herbert",
            "Isaac Asimov"
        };

        var list = new List<Book>();
        for (int i = 0; i < 10; ++i)
            list.Add(new Book
            {
                ID = i,
                Author = authors[i % authors.Length],
                Title = "Title " + i,
                Likes = i * i * 10
            });

        _books = list;
    }

    public IEnumerable<Book> Books
    {
        get { return _books; }
    }
}

We want to display a list of book that changes following the number of people
who liked the book.

If we have more than 100 likes, we’ll say that a lot of people like this
book. Under 100 likes we’ll say that not a lot of people likes it. And if we
have no likes, guess what, no one likes it.

Converters provides us with a way of doing that. But creating a class just
for this is not of a big interest for the rest of the application. Therefore we
will use a RelayConverter. Here is how to declare the Xaml :

<UserControl x:Class="nRoute_RelayConverters.MainPage"
    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:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:n="http://nRoute/schemas/2010/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <UserControl.Resources>
        <n:ValueConverterRelay x:Name="BookValueConverterRelay" />
    </UserControl.Resources>

    <i:Interaction.Behaviors>
        <n:BridgeViewModelBehavior />
        <n:BridgeValueConverterBehavior ValueConverterRelay="{StaticResource BookValueConverterRelay}" />
    </i:Interaction.Behaviors>

    <StackPanel x:Name="LayoutRoot" Background="White">
        <ItemsControl ItemsSource="{Binding Books}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch">
                        <TextBlock Text="{Binding Converter={StaticResource BookValueConverterRelay}}" />
                    </StackPanel>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </StackPanel>
</UserControl>

As we can see, it really looks like the declaration of a RelayCommand. The
only difference is that until now, we have declared the converter but not
defined the method to use to convert. And for this, let’s go to the code-behind.

First we need to add a using :

using nRoute.Components;

This using gives us access to nRoute’s extension methods. One of them,
SetRelayConverter, allows us to define the conversion method used by the
RelayConverter. Here is how it is used :

[MapView(typeof(ViewModels.MainPageViewModel))]
public partial class MainPage
{
    public MainPage()
    {
        InitializeComponent();

        this.SetRelayConverter<Book, string>("BookValueConverterRelay", BookValueConverterIn);
    }

    private static string BookValueConverterIn(Book book)
    {
        if (book.Likes > 100)
            return string.Format("A lot of people likes {0} by {1} !", book.Title, book.Author);
        else if (book.Likes > 1)
            return string.Format("Not a lot of people likes {0} by {1}.", book.Title, book.Author);
        return string.Format("No one likes {0} by {1}...", book.Title, book.Author);
    }
}

SetRelayConverter is a generic function taking two typed parameters (input
type parameter and output type parameter) and two parameters (the
RelayConverter’s name and the conversion method to use).

Finally, a little bit of code-behind for a strictly view issue, a class saved
and yes it’s still MVVM.

 

As usual you can get the sources of the article on my Skydrive.

nRoute – CommandRelay – Get access to a control’s context from a DataTemplate

One common issue when using the MVVM pattern from a Silverlight 4 application is to have access to the current control’s data context from items controls’ data templates.

Let’s look at the following application :

clip_image001[4]

It is composed of a data grid bound to a collection of books. Inside the view model that contains this collection, we can also find a command that displays books.

Here is the source code of this page, it’s view model and the book class :

public class Book
{
    public long ID { get; set; }
    public string Author { get; set; }
    public string Title { get; set; }
}
public class MainPageViewModel : ViewModelBase
{
    private readonly IEnumerable<Book> _books;
    private readonly ICommand _showAuthorCommand;

    public MainPageViewModel()
    {
        var list = new List<Book>();
        for (int i = 0; i < 10; ++i)
            list.Add(new Book
            {
                ID = i,
                Author = "Author " + i,
                Title = "Title " + i
            });

        _books = list;
        _showAuthorCommand = new ActionCommand<Book>(ShowAuthor);
    }

    public IEnumerable<Book> Books
    {
        get { return _books; }
    }

    public ICommand ShowAuthorCommand
    {
        get { return _showAuthorCommand; }
    }

    private static void ShowAuthor(Book book)
    {
        MessageBox.Show(book.Author);
    }
}
<Grid x:Name="LayoutRoot" Background="White">
    <sdk:DataGrid ItemsSource="{Binding Books}">
        <sdk:DataGrid.Columns>
            <sdk:DataGridTemplateColumn>
                <sdk:DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Button Content="Show Author"
                                Command="{Binding ShowAuthorCommand}"
                                CommandParameter="{Binding}" />
                    </DataTemplate>
                </sdk:DataGridTemplateColumn.CellTemplate>
            </sdk:DataGridTemplateColumn>
        </sdk:DataGrid.Columns>
    </sdk:DataGrid>
</Grid>

What we want to do here is calling the ShowAuthorCommand command of the page’s view model passing it the current book as a parameter in order to do some sort of computing (here we will just display the book’s author in a MessageBox).

But if we execute the code above, the command is not invoked. The button used to invoke it is inside a data template and therefore, its data context is a book and not the page’s view model and so it is impossible to use the command directly.

The data template does not have access to the page’s view model but it has access to the static resources defined in the page.

What we will do with nRoute is to save the command inside a static resource at the page level and invoke it. This concept is not specific to nRoute and can be reimplemented in another way. I just think it is beautifully implemented in Route.

First we will create an instance of CommandRelay inside the page’s static resources (it is not the same and the RelayCommand from MVVMLightToolkit). You can translate the hereafter in english by “I declare a variable named ShowAuthorCommandRelay” :

<UserControl.Resources>
    <n:CommandRelay x:Key="ShowAuthorCommandRelay" />
</UserControl.Resources>

Then inside the page’s behavior, in addition to the BridgeViewModelBehavior that maps the vue and its view model, we add a BridgeCommandBehavior that will initialise the instance of the CommandRelay previously declared :

<i:Interaction.Behaviors>
    <n:BridgeViewModelBehavior />
    <n:BridgeCommandBehavior CommandRelay="{StaticResource ShowAuthorCommandRelay}"
                                CommandSource="{Binding ShowAuthorCommand}" />
</i:Interaction.Behaviors>

The CommandRelay property is set to the CommandRelay to initialize and the CommandSource property is set to the command (here it’s the ShowAuthorCommand command from our view model).

You can translate the lines of code above in english by : “Initialize ShowAuthorCommandRelay with the ShowAuthorCommand command”.

Now we just need to invoke the command in the button using the following code :

<DataTemplate>
    <Button Content="Show Author"
            Command="{Binding Command, Source={StaticResource ShowAuthorCommandRelay}}"
            CommandParameter="{Binding}" />
</DataTemplate>

We see that the syntax used to invoke the command has changed since our first try. Here we use the Command property of the ShowAuthorCommandRelay static resource. Because as previously said, we can access static resources from a DataTemplate.

If we execute the code corrected we can see that the MessageBox shows up correctly.

NB : In Silverlight 5, in this kind of scenario we would probably have used one of the new binding options known as RelativeSource AncestorType but the CommandRelay’s technique will still be valid.

As usual you can download the source code of the application on my Skydrive.

nRoute – Messages – Opening a ChildWindow

One of the recurring aspects about MVVM programming is the use of messages. A message can be considered as a kind of an application wide event and therefore accessible from any part of it.

The idea with this pattern is to have a component which is referenced by any part of the application that wants to listen or to send messages. This component (which has given its name to the pattern) is commonly know as the mediator and allows us to create an architecture in which senders and listeners do not know each others in order to obtain a better modularity.

The nRoute framework includes a messenging framework that can send messages both synchronously and asynchronously. This part of nRoute is based on the Rx framework for its implementation. Those who have already used Rx will feel confortable.

One common problem when following the MVVM pattern is to open a ChildWindow from a view model and to get its results when it’s closed in the view model.
We will now see how to do this by using messages.

0 – The context

We build an application that displays a list of contacts which we will be able to edit when clicking on a button. This button will open a ChildWindow displaying the fields to edit the contact. It will also be possible to validate or to cancel the changes.
Here are the screenshots of what is expected :

mvvm-messages-1

Figure 1

mvvm-message-2

Figure 2

1 – The view

Our main control is Home.xaml. This is the one showed on figure 1. The Xaml code of this control contains a ListBox templated to display the contacts and a Button bound to a command that opens the contact’s edition ChildWindow.

Here’s the Xaml of this control :

<UserControl x:Class="nRoute_MVVM_ChildWindow.Views.Home"
    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:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
    xmlns:n="http://nRoute/schemas/2010/xaml"
    mc:Ignorable="d">

    <i:Interaction.Behaviors>
        <n:BridgeViewModelBehavior />
    </i:Interaction.Behaviors>

    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="350" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

        <ListBox x:Name="lstBox" ItemsSource="{Binding Contacts}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding FirstName}" />
                        <TextBlock Text=" " />
                        <TextBlock Text="{Binding LastName}" />
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

        <Button
            Grid.Row="1"
            Content="Edit"
            Command="{Binding EditContactCommand}"
            CommandParameter="{Binding Path=SelectedItem, ElementName=lstBox}" />
    </Grid>
</UserControl>

And its code-behind :

[nRoute.ViewModels.MapView(typeof(ViewModels.HomeViewModel))]
public partial class Home
{
    public Home()
    {
        InitializeComponent();
    }
}

2 – The view-models

You can see here that thanks to the MapView attribute, the Home control is linked to the HomeViewModel. But before defining this view-model let’s fist define the model representing the contacts:

public class ContactViewModel : ViewModelBase, IEditableObject
{
    private string _firstName;
    private string _lastName;
    private ContactViewModel _originalValue;

    public long Id { get; set; }

    public string FirstName
    {
        get
        {
            return _firstName;
        }

        set
        {
            if (_firstName != value)
            {
                _firstName = value;
                NotifyPropertyChanged(() => FirstName);
            }
        }
    }

    public string LastName
    {
        get
        {
            return _lastName;
        }

        set
        {
            if (_lastName != value)
            {
                _lastName = value;
                NotifyPropertyChanged(() => LastName);
            }
        }
    }

    public void BeginEdit()
    {
        _originalValue = new ContactViewModel
        {
            FirstName = FirstName,
            LastName = LastName
        };
    }

    public void CancelEdit()
    {
        if (_originalValue != null)
        {
            LastName = _originalValue.LastName;
            FirstName = _originalValue.FirstName;
            _originalValue = null;
        }
    }

    public void EndEdit()
    {
        _originalValue = null;
    }
}

The particularity of this view-model is that it implements the IEditableObject interface which you can find in the System.ComponentModel namespace. This interface defines three methods we’ll use to create the contact’s edition form of the ChildWindow :

- BeginEdit (sets the object in a edit state)

- CancelEdit (cancels all modifications and stops the edition)

- EndEdit (validates all modifications and stops the edition)

And now here’s the HomeViewModel :

public class HomeViewModel : ViewModelBase
{
    private readonly ICommand _editCommand;
    private readonly ObservableCollection<ContactViewModel> _contacts;

    public HomeViewModel()
    {
        _contacts = new ObservableCollection<ContactViewModel>();
        _editCommand = new ActionCommand<ContactViewModel>(BeginContactEdition);

        for (int i = 0; i < 10; i++)
            _contacts.Add(new ContactViewModel
            {
                Id = i,
                FirstName = "FirstName" + i,
                LastName = "LastName" + i
            });
    }

    public IEnumerable<ContactViewModel> Contacts
    {
        get
        {
            return _contacts;
        }
    }

    public ICommand EditContactCommand
    {
        get
        {
            return _editCommand;
        }
    }

    private void BeginContactEdition(ContactViewModel contact)
    {
    }
}

In its current state, the view model generates a list of 10 elements and defines the EditContactCommand command that is called whenever the Edit button is clicked. Therefore, it is in the BeginContactEdition method that we want to open the ChildWindow passing it the current contact.

3 – The ChildWindow

We will now add a ChildWindow to the project using Visual Studio’s template and modify it to make the Xaml be like this :

<controls:ChildWindow x:Class="nRoute_MVVM_ChildWindow.ChildWindows.ContactChildWindow"
           xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
           xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
           xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
           Width="400" Height="300"
           Title="ContactChildWindow">

    <Grid x:Name="LayoutRoot" Margin="2">
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <StackPanel>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="First name : " />
                <TextBox Width="100" Text="{Binding FirstName, Mode=TwoWay}" />
            </StackPanel>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="Last name : " />
                <TextBox Width="100" Text="{Binding LastName, Mode=TwoWay}" />
            </StackPanel>
        </StackPanel>

        <Button x:Name="CancelButton" Content="Cancel" Click="CancelButton_Click" Width="75" Height="23" HorizontalAlignment="Right" Margin="0,12,0,0" Grid.Row="1" />
        <Button x:Name="OKButton" Content="OK" Click="OKButton_Click" Width="75" Height="23" HorizontalAlignment="Right" Margin="0,12,79,0" Grid.Row="1" />
    </Grid>
</controls:ChildWindow>

4 – Creation of messages

The mediator pattern induces three things :

- We need a message to send

- We need something to send the message

- We need at least one control that listens to the message

The control sending the message must provide enough information inside the message in order to make it useful for the controls that listens to it.

In our application we will have two messages, one to trigger the contact’s edition and another one to inform that the contact’s edition is finished.

public class BeginContactEditionMessage
{
    public ContactViewModel Contact { get; set; }
}
public class EndContactEditionMessage
{
    public ContactViewModel Contact { get; set; }

    public bool Success { get; set; }
}

5 – Sending and receiving messages

Now that we have messages we need to send them. And as everyone should be expecting, we will start by the one that triggers the contact’s edition.

Let’s go back to the HomeViewModel class and add the following field :

private readonly IChannel<BeginContactEditionMessage> _beginContactEditionChannel;

We will initialize it inside the constructor with the default communication channel associated with the BeginContactEditionMessage message (private channels also exists but it is out of the scope of this article) :

_beginContactEditionChannel = Channel<BeginContactEditionMessage>.Public;

We now need to modify BeginContactEdition with the following code :

private void BeginContactEdition(ContactViewModel contact)
{
    var message = new BeginContactEditionMessage
    {
        Contact = contact
    };

    contact.BeginEdit();
    _beginContactEditionChannel.OnNext(message);
}

The OnNext method sends a message to all listeners (those who have already used Rx will feel confortable here). The message is now being sent but nothing listens to it.
The one that should listen to it is of course the ChildWindow. Let’s modify its code-behind a little to make it react to the messages sent by the view-model.

We will add two line to it’s constructor :

var channel = Channel<BeginContactEditionMessage>.Public;
_beginContactEditionChannelDisposable = channel.Subscribe(BeginContactEdition);

As in the view model, we get the public instance of the communication channel but this time we will not call OnNext (which stands for Send) but Subscribe (which stands for Listen). The Subscribe method takes an Action<T> as a parameter which will be called whenever a message is sent and returns an IDisposable object we must dispose to unsubscribe from the channel.

For the moment, we will save this value in a field :

private readonly IDisposable _beginContactEditionChannelDisposable;

Then we will implement the BeginContactEdition method :

private void BeginContactEdition(BeginContactEditionMessage m)
{
    DataContext = m.Contact;
    Show();
}

In order to make things correctly we’ll make the ChildWindow implement IDisposable :

public void Dispose()
{
    _beginContactEditionChannelDisposable.Dispose();
}

And that’s it ! Now, when we select a contact in the ListBox and then click on the button the ChildWindow opens with the selected contact in edition mode. But the view model is never notified when the contact’s edition is finished.

We will do the same thing for the EndContactEdition message that what we did the BeginContactEdition but reversing the roles of sender and listener.

In the ChildWindow’s code-behind we will replace the event handlers of the buttons OK and Cancel by the following code :

private void OKButton_Click(object sender, RoutedEventArgs e)
{
    DialogResult = true;
    PublishResult();
}

private void CancelButton_Click(object sender, RoutedEventArgs e)
{
    DialogResult = false;
    PublishResult();
}

private void PublishResult()
{
    var contact = (ContactViewModel)DataContext;
    var channel = Channel<EndContactEditionMessage>.Public;
    var message = new EndContactEditionMessage
    {
        Contact = contact,
        Success = DialogResult.HasValue && DialogResult.Value
    };

    channel.OnNext(message);
}

Let’s go back to the view model and follow the same method for the EndContactEditionMessage message that the one use in the ChildWindow’s code-behind to receive the BeginContactEditionMessage.

Creation of the IDisposable field :

private readonly IDisposable _endContactEditionChannelDisposable;

Modification of the view model’s constructor :

_endContactEditionChannel = Channel<EndContactEditionMessage>.Public;
_endContactEditionChannelDisposable = _endContactEditionChannel.Subscribe(
    m =>
    {
        if (m.Success)
            m.Contact.EndEdit();
        else
            m.Contact.CancelEdit();
    });

Make the view model implement the IDisposable interface :

public void Dispose()
{
    _endContactEditionChannelDisposable.Dispose();
}

I hope that you’ll find this article useful.

As usual, you can download the sources of the articles on my Skydrive.

nRoute – Reverse commands

Introduction

In a previous article, I had talked about using commands with nRoute. Just to remind you, commands allow the view to send messages to the view model which will in turn execute a particular action. But what if, from the view model, we need to send a message to the view to change, for example, the visual state of a control with its VisualStateManager?

ReverseCommands has been created precisely for this purpose.

Context

In order to illustrate this article, we will first create a simple Silverlight application. Here is the Xaml code from the MainPage :

<UserControl x:Class="nRoute_ReverseCommands.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:ei="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions" xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" xmlns:n="http://nRoute/schemas/2010/xaml"> <i:Interaction.Behaviors> <n:BridgeViewModelBehavior /> </i:Interaction.Behaviors> <Grid x:Name="LayoutRoot" Background="White"> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="VisualStateGroup"> <VisualState x:Name="RedState"> <Storyboard> <ColorAnimation Duration="0" To="Red" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="rectangle" /> </Storyboard> </VisualState> <VisualState x:Name="BlueState"> <Storyboard> <ColorAnimation Duration="0" To="Blue" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="rectangle" /> </Storyboard> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <Rectangle x:Name="rectangle" Width="50" Height="50" Fill="Transparent" /> </Grid> </UserControl>    

The grid has two visual states : one will paint the rectangle in blue, the other in red.

The goal of this example is to change the color of the rectangle every second using its visual states and reverse commands.

Here is the starting view model :

public class MainPageViewModel : ViewModelBase {
    private bool _ok;
    private readonly DispatcherTimer _timer;

    public MainPageViewModel()
    {
        _timer = new DispatcherTimer();
        _timer.Interval = TimeSpan.FromSeconds(1);
        _timer.Tick += (s, a) => OnTimerTick();
        _timer.Start();
    }

    private void OnTimerTick()
    {
        // Changer l'état visuel _ok = !_ok;
    }
}

 

Commands creation and initialization

In the above code, we initialize a timer which calls the OnTimerTick method every second. In this method, we have to order the view to change the visual state. For this, we will create two reverse commands :

private readonly IReverseCommand _okCommand;
private readonly IReverseCommand _koCommand;

And not forget to initialize them with an empty action in the constructor of the view model :

_okCommand = new ActionCommand(() => { });
_koCommand = new ActionCommand(() => { });

We can see here that the ActionCommands that we have previously used implement IReverseCommand. Howerer, the initialization of a reverse command has nothing different from one of a normal command. What changes is its use : we initialized the command with an empty action because we don’t have actions from the view to treat.

If we look at the definition of IReverseCommand, we can see that it exposes only one event named CommandExecuted. We will see how this will permit us to execute an action in the view a little further.

Now that our commands are initialized, we will be able to use them. We will modify the corpse of the OnTimerTick method in order to execute the reverse commands Ok and Ko alternately :

private void OnTimerTick()
{
    if (_ok)
        _okCommand.Execute(null);
    else _koCommand.Execute(null);
    _ok = !_ok;
}

We must also expose it to the view, so we add two properties :

public ICommand OkCommand { get { return _okCommand; } }
public ICommand KoCommand { get { return _koCommand; } }

 

Linking reverse commands to the view

We finished the view model and it is now time to return to the view so we can use the exposed reverse commands. For this, nRoute provides a trigger that will subscribes to the CommandExecuted event exposed by the IReverseCommand interface, allowing us to execute the action in the view. This trigger is called ReverseCommandTrigger and we will see now how we can use it.

In the Xaml of the MainPage, we will add triggers under the declaration of the visual states (VisualStateManager.VisualStateGroups).

<i:Interaction.Triggers> <n:ReverseCommandTrigger ReverseCommand="{Binding OkCommand}"> <ei:GoToStateAction StateName="BlueState" /> </n:ReverseCommandTrigger> <n:ReverseCommandTrigger ReverseCommand="{Binding KoCommand}"> <ei:GoToStateAction StateName="RedState" /> </n:ReverseCommandTrigger> </i:Interaction.Triggers> 

The declaration is quite clear and speaks for itself. When the OkCommand is invoked, we load the “BlueState” visual state. When it is the KoCommand that is invoked, we load the “RedState” visual state. Instead of changing the visual state, we could have taken other actions like launching a storyboard, navigate, etc. It’s now up to the view to choose.

If we now launch the application, we have a beautiful and lovely rectangle which changes color every second.

You can find the source code of this article on my skydrive.

It’s up to you now !