Tuesday, December 7, 2010

IronPython & Silverlight Part II: Basic event handling

There are a couple of ways to add event handlers to Silverlight controls. The common way is to add the event handlers directly in XAML. For example:

<Button x:Name="ButtonGo" Content="Go!" Click="MyClickHandler" />


Given that there's a definition for the MyClickHandler method in your C# code. However for IronPython there's a couple of options:

Directly in Python code



Event handlers can be added as in C# by using the '+=' operator. For example say that you have the following XAML code describing an UserControl:

<UserControl x:Class="System.Windows.Controls.UserControl"
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<StackPanel Width="300" x:Name="layout_root" Background="White">
<TextBlock x:Name="Message" FontSize="30" />
<Button x:Name="ButtonGo" Content="Go!" />
</StackPanel>
<UserControl.Resources>
<Storyboard x:Name="MyStoryboard">
<DoubleAnimation
Storyboard.TargetName="Message"
Storyboard.TargetProperty="Opacity"
From="1.0" To="0.0" Duration="0:0:3"
AutoReverse="True"
RepeatBehavior="Forever"/>
</Storyboard>
</UserControl.Resources>
</UserControl>


Say we want to start the 'MyStoryboard' animation in the event handler for the Click event of the ButtonGo button. We can write:

from System.Windows import Application
from System.Windows.Controls import UserControl

def handle_click(sender, event_args):
theApp.root.MyStoryboard.Begin()

class App:

def __init__(self):
self.root = Application.Current.LoadRootVisual(MyUserControl(), "app.xaml")
self.root.Message.Text = "Welcome to Python and Silverlight!"
self.root.ButtonGo.Click += handle_click

theApp = App()


Using clrtype



The clrtype module can be used to define .NET classes from (Iron)Python classes . This module can be found in the IronPython samples package or here in the GitHub repository. The GUI Automated Testing blog has some nice tutorials on using clrtype.

To use this module, you have to copy the clrtype.py file to your app/ folder.

We can change the code this way:

from System.Windows import Application
from System.Windows.Controls import UserControl
from System.Windows import MessageBox
import System
import clrtype

class MyUserControl(UserControl):
__metaclass__ = clrtype.ClrClass

_clrnamespace = "MyNs"

@clrtype.accepts(System.Object, System.EventArgs)
@clrtype.returns(System.Void)
def my_click_handler(self, sender, event_args):
theApp.root.MyStoryboard.Begin()


def __getattr__(self, name):
return self.FindName(name)

def handle_click(sender,event_args):
theApp.root.MyStoryboard.Begin()

class App:

def __init__(self):
self.root = Application.Current.LoadRootVisual(MyUserControl(), "app.xaml")
self.root.Message.Text = "Welcome to Python and Silverlight!"

theApp = App()


With these definitions we can change the XAML code for the Button to have be:

<Button x:Name="ButtonGo" Content="Go!" Click="my_click_handler"/>


Notice that the definition of MyUserControl has a definition for __getattr__. This definition is used to still be able to access the definitions of child controls for example theApp.root.MyStoryboard.

Final words



Another way to do event handling is to use Commanding. This approach is preferred for MVVM. For future posts I'll try to cover the use of Commanding with IronPython.