Saturday, January 29, 2011

IronPython & Silverlight Part V: Using the MVVM Light Toolkit

In this post I'm going to show a small example of using the MVVM Light Toolkit in Silverlight with IronPython.

MVVM Light


According to its website, MVVM Light Toolkit is a:

...set of components helping people to get started in the Model - View - ViewModel pattern in Silverlight and WPF...

It provides useful elements such an implementation of "Relay Command" and a feature to expose events as commands (EventToCommand).

In the context of IronPython it will save us a lot of code.

Adding a reference to MVVM Light


There are several ways to add a reference to the MVVM Light Toolkit assembly. However the first step is to set the Silverlight version to 4 (see this post for more information).

Adding the reference using the manifest


One way to add the reference is to use the manifest AppManifest.xaml. Once we generated this file(using chiron.exe /m and copying it to app/) and changed the Silverlight version to 4 (see here) we can add an entry referencing the GalaSoft.MvvmLight.SL4.dll assembly.

<Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
RuntimeVersion="4.0.50401.0"
EntryPointAssembly="Microsoft.Scripting.Silverlight"
EntryPointType="Microsoft.Scripting.Silverlight.DynamicApplication"
ExternalCallersFromCrossDomain="ScriptableOnly">
<!-- Add assembly references here -->
<Deployment.Parts>
...
<AssemblyPart Source="GalaSoft.MvvmLight.SL4.dll"/>
...
</Deployment.Parts>
...
</Deployment>

Also we need to copy of the GalaSoft.MvvmLight.SL4.dll file to the chiron.exe folder (ex. IronPython\Silvelright\bin).


Using it in Python


Once we referenced this file using the manifest we need to reference it from code.
import clr
clr.AddReferenceToFile('GalaSoft.MvvmLight.SL4.dll')


Example


The following example shows the use of RelayCommand and ViewModelBase from IronPython.

app.xaml:

<UserControl x:Class="System.Windows.Controls.UserControl"
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wbc="clr-namespace:System.Windows.Controls">
<StackPanel Width="300" x:Name="layout_root" Background="White">
<TextBox x:Name="my_text_box"
Text="{Binding text_to_display, Mode=TwoWay}" />

<TextBlock Text="{Binding text_to_display}" />
<Button Content="Reset" Command="{Binding reset_command}"/>
</StackPanel>
</UserControl>


app.py:

import clr
clr.AddReferenceToFile('GalaSoft.MvvmLight.SL4.dll')
from System.Windows import Application
from System.Windows.Controls import UserControl
import System
import clrtype
from System.Windows import MessageBox
from GalaSoft.MvvmLight.Command import RelayCommand
from GalaSoft.MvvmLight import ViewModelBase

class MyBasicModel(ViewModelBase):
__metaclass__ = clrtype.ClrClass

def __init__(self):
self.text = 'Initial text'

@property
@clrtype.accepts()
@clrtype.returns(System.String)
def text_to_display(self): return self.text


@text_to_display.setter
@clrtype.accepts(System.String)
@clrtype.returns()
def text_to_display(self, value):
self.text = value
self.RaisePropertyChanged('text_to_display')

@property
@clrtype.accepts()
@clrtype.returns(System.Object)
def reset_command(self):
return RelayCommand(lambda: self.perform_reset_text() )

def perform_reset_text(self):
self.text_to_display = ''


class App:

def __init__(self):

self.model = MyBasicModel()
self.root = Application.Current.LoadRootVisual(UserControl(), "app.xaml")
self.root.DataContext = self.model


theApp = App()


Using this library from IronPython saves us from many thins such as having to declare events to comply with the INotifyPropertyChanged interface.