Tag Archives: Silverlight

Calculate EndpointAddress for Silverlight client

Because Silverlight checks the origin it considers http://localhost and http://127.0.0.1 as different locations. In case you want your visitors to be able to use both addresses you can recalculate the address as following:

EndpointAddress GetEndpointAddress(EndpointAddress endpointAddress)
{
 var scheme = Application.Current.Host.Source.GetComponents(UriComponents.Scheme, UriFormat.Unescaped);
 var serverAndPort = Application.Current.Host.Source.GetComponents(UriComponents.HostAndPort, UriFormat.Unescaped);
 var pathAndQuery = endpointAddress.Uri.GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped);
 return new EndpointAddress(scheme + "://" + serverAndPort + pathAndQuery);
}

And you can use this method as following:

var client = new DirectoryServiceClient();
client.Endpoint.Address = GetEndpointAddress(client.Endpoint.Address);
client.GetMessageCompleted += ClientGetMessageCompleted;
client.GetMessageAsync();

Creating graphs with the Silverlight Toolkit

As i wrote already: In a chart the elements on the X-axis are usually numbers or dates, and the elements on the Y-axis are usually doubles. We can define such a combination as following:

public class Point<t>
{
 public T X { get; set; }
 public double Y { get; set; }
}

Here is a little helper function for creating line series that are used by the Silverlight Toolkit:

public LineSeries Create<t>(string title, Series<t> series, Func<t, double> f) where T : IComparable<t>
{
 var points = series.Select(x => new Point<t> { X = x, Y = f(x) });

 var lineSeries = new LineSeries
 {
  Title = title,
  ItemsSource = points,
  IndependentValuePath = "X",
  DependentValuePath = "Y"
 };

 return lineSeries;
}

Given all this infrastructure we can easily draw the graph of a function:

public MainPage()
{
 InitializeComponent();

 var series = 0.To(100);

 Func<int, double> multiplyByTwo = x => 2 * x;
 Chart1.Series.Add(Create("2x", series, multiplyByTwo));

 Func<int, double> multiplyByThree = x => 3 * x;
 Chart1.Series.Add(Create("x/2", series, multiplyByThree));
}

Here is how the result looks like (too much data on the chart):

screenshot of chart in silverlight toolkit

Silverlight and unit testing..

A while ago i was looking for a unittesting framework that can be used with Silverlight. Because i don’t want to launch a webbrowser on my buildserver i ruled the Unit Test Framework for Microsoft Silverlight out. A couple of websearches later i decided to try a Silverlight port of good ol’ NUnit, nunitsilverlight, and was pretty pleased with results.

A couple of things to keep in mind though:

  • Make sure your test runner loads the correct System assembly (Possible solution: set Copy Local to true in your test project)
  • In case your test runner has to run tests in both ‘regular’ and ‘silverlight’ assemblies, make sure that your runner uses separate AppDomains (For NUnit use the /Domain=Multiple option)

Couple of methods missing on ObservableCollection

Here are a couple of methods that are missing on ObservableCollection<T>:

public static class ObservableCollectionExtensions
{
 public static void AddRange<t>(this ObservableCollection<t> observableCollection, IEnumerable<t> elements)
 {
  foreach (var element in elements) observableCollection.Add(element);
 }

 public static ObservableCollection<t> Create<t>(IEnumerable<t> elements)
 {
  var observableCollection = new ObservableCollection<t>();
  observableCollection.AddRange(elements);
  return observableCollection;
 }
}

Separation of concerns: Behavior = Trigger + TriggerAction

If you look at my KeyBehavior you notice that it is doing two things: register for events so that the behavior can be triggered and handle the actual command invocation. In order to enhance reuse we can refactor this KeyBehavior in a KeyTrigger and an InvokeCommandAction. Well, we’re not going to do that, because they exist already in the silverlight sdk ;)

A shortcoming of the InvokeCommandAction is that it can only invoke commands on the FrameworkElement itself, thus we write a custom implementation that finds commands on the DataContext instead:

public class InvokeCommandAction : TriggerAction<frameworkElement>
{
 public string CommandName { get; set; }

 protected override void Invoke(object parameter)
 {
  var viewModel = AssociatedObject.DataContext;
  GetCommandAndExecuteIt(viewModel, CommandName);
 }

 void GetCommandAndExecuteIt(object viewModel, string commandName)
 {
  var command = viewModel.GetPropertyValue<icommand>(commandName);
  if(command.CanExecute(null)) command.Execute(null);
 }
}

And now we can drag this action on our design surface in Blend and select a trigger that goes with it:

choosing a keypress trigger in blend

All we have to do is choose the Key and Command to invoke:

setting properties for action in blend

In XAML this looks like:

<interactivity:Interaction.Triggers>
 <ii:KeyTrigger Key="Right">
  <inf:InvokeCommandAction CommandName="PlayerRight"/>
 </ii:KeyTrigger>
 <ii:KeyTrigger Key="Left">
  <inf:InvokeCommandAction CommandName="PlayerLeft"/>
 </ii:KeyTrigger>
 <ii:KeyTrigger Key="Up">
  <inf:InvokeCommandAction CommandName="PlayerUp"/>
 </ii:KeyTrigger>
 <ii:KeyTrigger Key="Down">
  <inf:InvokeCommandAction CommandName="PlayerDown"/>
 </ii:KeyTrigger>
</interactivity:Interaction.Triggers>

I guess this ends our exploration of the behavior features in Silverlight.

True KeyBehavior with System.Windows.Interactivity.Behavior

Yesterday i demonstrated how attached properties can be used to invoke commands on specific key presses (and releases). With the aid of System.Windows.Interactivity.Behavior we can implement a true behavior and we get an extension point to do the required cleanup.

screenshot of Blend managing a KeyBehavior

<grid>
 <interactivity:Interaction.Behaviors>
  <inf:KeyBehavior>
   <inf:KeyBehavior.DownKeyCommands>
    <inf:KeyCommandName Key="Right" CommandName="PlayerRight"  />
    <inf:KeyCommandName Key="Left" CommandName="PlayerLeft" />
    <inf:KeyCommandName Key="Up" CommandName="PlayerUp" />
    <inf:KeyCommandName Key="Down" CommandName="PlayerDown" />
   </inf:KeyBehavior.DownKeyCommands>
  </inf:KeyBehavior>
 </interactivity:Interaction.Behaviors>
 ...
</grid>

The behavior implementation is the same as yesterday, only this time we thankfully override the OnAttached and OnDetaching methods:

public class KeyBehavior : Behavior<frameworkElement>
{
 public List<keyCommandName> DownKeyCommands { get; set; }
 public List<keyCommandName> UpKeyCommands { get; set; }

 public KeyBehavior()
  : base()
 {
  DownKeyCommands = new List<keyCommandName>();
  UpKeyCommands = new List<keyCommandName>();
 }

 protected override void OnAttached()
 {
  base.OnAttached();
  SubscribeToKeyEvents();
 }

 protected override void OnDetaching()
 {
  UnsubscribeFromKeyEvents();
  base.OnDetaching();
 }

 void SubscribeToKeyEvents()
 {
  AssociatedObject.KeyDown += AssociatedObject_KeyDown;
  AssociatedObject.KeyUp += AssociatedObject_KeyUp;
 }

 void UnsubscribeFromKeyEvents()
 {
  AssociatedObject.KeyDown -= AssociatedObject_KeyDown;
  AssociatedObject.KeyUp -= AssociatedObject_KeyUp;
 }

 ...

Silverlight: leveraging attached properties to handle key events

I strongly believe that input handling is a responsability that belongs to the View. At first i simply added the following in the code-behind of my GameView:

protected override void OnKeyDown(KeyEventArgs e)
{
 base.OnKeyDown(e);

 if (e.Key == Key.Left) Model.MovePlayerLeft();
 ...
}

But i wanted to play with the cool kids so i exposed ICommand properties on my ViewModel instead and rewrote the code like this:

protected override void OnKeyDown(KeyEventArgs e)
{
 base.OnKeyDown(e);

 if (e.Key == Key.Left) Model.PlayerLeft.Execute(null);
 ...

Offcourse, designers should not have to write code at all, thus i searched for a different solution. Because there isn’t a behavior that allows me to differentiate the command based on the actual key being pressed i wrote my own KeyEvents class which allows the designer to map a key to a command. Here is an example:

 <inf:KeyEvents.Down>
  <inf:KeyCommand Key="Right" CommandName="PlayerRight"  />
  <inf:KeyCommand Key="Left" CommandName="PlayerLeft" />
  <inf:KeyCommand Key="Up" CommandName="PlayerUp" />
  <inf:KeyCommand Key="Down" CommandName="PlayerDown" />
 </inf:KeyEvents.Down>
 ...
</grid>

The down property is nothing more than an attached property:

public static readonly DependencyProperty DownProperty =
 DependencyProperty.RegisterAttached("Down", typeof(List<keyCommand>), typeof(KeyEvents), new PropertyMetadata(null, OnSetDownCallback));

A KeyCommand is a simple pair of a Key and a Command name:

public class KeyCommand
{
 public Key Key { get; set; }
 public string CommandName { get; set; }
}

The GetDown method (for the attached Down property) will instantiate a KeyBehavior class which hooks up to the element’s KeyDown and KeyUp events and uses a bit of reflection to find the commands…

public class KeyBehavior
{
 public KeyBehavior(FrameworkElement frameworkElement)
 {
  FrameworkElement = frameworkElement;
  DownKeyCommands = new List<keyCommand>();
  UpKeyCommands = new List<keyCommand>();

  frameworkElement.KeyDown += frameworkElement_KeyDown;
  frameworkElement.KeyUp += frameworkElement_KeyUp;
 }

 public FrameworkElement FrameworkElement { get; set; }
 public IList<keyCommand> DownKeyCommands { get; set; }
 public IList<keyCommand> UpKeyCommands { get; set; }

 void frameworkElement_KeyUp(object sender, KeyEventArgs e)
 {
  ExecuteCommandsForKey(e.Key, UpKeyCommands);
 }

 void frameworkElement_KeyDown(object sender, KeyEventArgs e)
 {
  ExecuteCommandsForKey(e.Key, DownKeyCommands);
 }

 void ExecuteCommandsForKey(Key key, IEnumerable<keyCommand> commands)
 {
  var commandNamesForKey = commands.Where(p => p.Key == key).Select(p => p.CommandName);
  var viewModel = FrameworkElement.DataContext;
  foreach (var command in commandNamesForKey) GetCommandAndExecuteIt(viewModel, command);
 }

 void GetCommandAndExecuteIt(object model, string name)
 {
  var command = GetCommand(model, name);
  command.Execute(null);
 }

 ICommand GetCommand(object model, string name)
 {
  return (ICommand)model.GetType().GetProperty(name).GetValue(model, null);
 }
}

The only thing that is missing is a way to unsubscribe from the events (and so you will end up with memory leaks). WeakReferences may come of use but i’ll leave that as an exercise for the reader. Many thanks go to the WPF Disciples because they inspired me to come up with this attached properties magic.

Exploring graphical programming with Blend, Visual State Manager and Behaviors

A while ago i presented the ControlStateMachine and in Silverlight this concept is implemented as the Visual State Manager.

In my sokoban implementation i have a cellview which exists out of 6 canvasses but only two of them (one for the cell type and one for the piece type) are visible at any given point in time. I have implemented this with 6 properties CanvasXVisible (with X being Player, Box, Wall, Goal, Floor and Cell) in my ViewModel but a State Machine / Manager may help clarify how the visibility of the canvasses are related. Here are the 2 visual state groups and their states that i would need for the CellView:

screenshot of visual state manager in expression blend

As you can see there is quite a lof of XAML involved to make the correct canvas visible:

 <storyboard>
  <objectAnimationUsingKeyFrames BeginTime="00:00:00"  Duration="00:00:00.0010000"
   Storyboard.TargetName="Space"  Storyboard.TargetProperty="(UIElement.Visibility)">
    <discreteObjectKeyFrame KeyTime="00:00:00">
     <discreteObjectKeyFrame.Value>
      <visibility>Visible</visibility>
     </discreteObjectKeyFrame.Value>
    </discreteObjectKeyFrame>
   </objectAnimationUsingKeyFrames>
  </storyboard>
</visualState>

For a simple modification to the Visibility property this seems like overkill but in many situations you will want to change more than this one property.

With the aid of the behaviors that come with Blend i can quickly add a couple of radio buttons, toss in some gotostate actions and end up with an interactive application:

screenshot of gotostate action properties

 <i:Interaction.Triggers>
  <i:EventTrigger EventName="Checked">
   <ic:GoToStateAction StateName="Wall1"/>
  </i:EventTrigger>
 </i:Interaction.Triggers>
</radioButton>

Feel free to try it yourself by changing the radio buttons:

Conclusion: All in all it is relatively easy to create interactive applications using Blend without writing a single line of code. Too bad that the behaviors are in an Expression assembly and don’t come with standard Silverlight. Another attention point is the maintainability of this new style of programming.

ViewModel to translate domain messages to view events

Here is an example of a ViewModel that translates domain messages to view events:

class GameViewModel : INotifyPropertyChanged, IListener<boardChanged>
{
 public event PropertyChangedEventHandler PropertyChanged = delegate { };

 public GameViewModel()
 {
  var messageBus = ServiceLocator.MessageBus;
  messageBus.Subscribe<boardChanged>(this);
 }

 void IListener<boardChanged>.Handle(BoardChanged message)
 {
  PropertyChanged("Board");
 }
}

About databinding and composite views

A couple of days ago i had a databound ItemsControl (collection of Model.Cell) which instantiated sub views (with their own viewmodel).

 <grid.Resources>
  <dataTemplate x:Key="CellTemplate">
   <views:CellView />
  </dataTemplate>
 </grid.Resources>
 <itemsControl
   ItemTemplate="{StaticResource CellTemplate}"
   ItemsSource="{Binding Cells}" />
</grid>

Because each CellViewModel needs to know which cell they manage i used the following dirty hack:

public CellView()
{
 Loaded += CellView_Loaded;
}

void CellView_Loaded(object sender, RoutedEventArgs e)
{
 DataContext = new CellViewModel(DataContext);
}

Later on that day i realised there was a much cleaner solution: Let the BoardViewModel expose a collection of ViewModels.CellViewModel instead of Model.Cell. What a relief that i don’t have to use the Loaded event hack :)