XAML meets Boo

My first impression with XAML was that you get to play with it only if your building WPF apps in c#.  It seems the .NET3  c# compiler is the only one capable of compiling XAML markup and code into an executable file.  It was a big letdown for Boo aficionados like me since XAML is clearly the way to go when it comes to creating user interfaces in WPF. 

I was dead wrong. It seems any .NET language like Boo can still leverage XAML with a simple workaround as illustrated by Rob Relyea on his post about the 3 Coding Styles for Avalon Applications.

To see if Rob's workaround will work, I wrote the following markup in XamlPad and copy pasted it to a file called "Exer1.xaml" in my Boo project. I didn't want the Boo compiler to touch this markup at compile time so I set its Build action property to None and its Copy to output directory property to PreserveNewest. 

<StackPanel
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Margin="10">
    <DockPanel     Width="300" HorizontalAlignment="Left"    Margin="10 0 0 5">
        <StackPanel DockPanel.Dock="Left">
            <TextBox
                Name="textBox1"
                Width="230"
                FontSize="12"
                FontFamily="Tahoma"
                Margin="0 0 2 2"/>
        </StackPanel>
        <Button
            Name="addButton"
            DockPanel.Dock="Right"
            VerticalAlignment="Top"
            Width="60"
            Content="Add"/>
    </DockPanel>
    <DockPanel HorizontalAlignment="Left" Width="300" Margin="10 0 0 0">
        <StackPanel DockPanel.Dock="Left">
            <ListBox
                Name="listBox1"
                Width="230"
                Height="100"
                FontSize="12"
                FontFamily="Tahoma"
                Background="GhostWhite"
                Margin="0 0 2 2">            
            </ListBox>
        </StackPanel>
        <Button
            Name="delButton"
            DockPanel.Dock="Right"
            VerticalAlignment="Top"
            Width="60"
            Content="Delete"/>
    </DockPanel>
</StackPanel>

Create the markup with XamlPad

Next, I added the following Boo code to the project.  The logic of the program is simple. When you click on the Add button (addButton), whatever you enter in the TextBox (textBox1) is placed on the ListBox (listBox1) below it.  When you click on the Delete button (delButton), the selected item on the listbox will be removed.

namespace WinFx.Demo

import System
import System.Collections
import System.Windows
import System.Windows.Controls
import System.Windows.Controls.Primitives
import System.Windows.Input
import System.Windows.Media
import System.Windows.Markup
import System.Windows.Shapes
import System.IO
import System.Xml

class Exer1(Window):
	textBox1 as TextBox 
	listBox1 as ListBox
	addButton as Button
	delButton as Button
	
	def constructor():
		# parse the element tree via the XamlReader
		streamReader = StreamReader("Exer1.xaml")
		xmlreader = XmlReader.Create(streamReader)		
		view as Panel= XamlReader.Load(xmlreader)
		
		# get a reference to the named elements via the LogicalTreeHelper
		textBox1  = LogicalTreeHelper.FindLogicalNode(view, "textBox1")
		listBox1  = LogicalTreeHelper.FindLogicalNode(view, "listBox1")
		addButton  = LogicalTreeHelper.FindLogicalNode(view, "addButton")
		delButton  = LogicalTreeHelper.FindLogicalNode(view, "delButton")
		
		# wire up the elements to your code
		addButton.Click += AddButtonClick
		delButton.Click += DelButtonClick		
		
		# customize the window 
		self.Content = view
		self.WindowStartupLocation = WindowStartupLocation.CenterScreen
		self.Title = "XAML Meets Boo"
		self.Width = 500
		self.Height = 300
		
	protected def AddButtonClick(sender as object, e as RoutedEventArgs):
		listBox1.Items.Add(textBox1.Text)
		textBox1.Text = ""
		textBox1.Focus()
			
	protected def DelButtonClick(sender as object, e as RoutedEventArgs):
		index = listBox1.SelectedIndex
		if index >= 0:
			listBox1.Items.RemoveAt(index)
			
		
[STAThread]
def Main():
	app = Application()	
	Exer1().Show()
	app.Run()

Here's a screenshot of this in action.

Wiring XAML elements to code

The code above looks very much like a regular WinForm code except the contents of the window are defined in an external XAML file. Shades of ASP.NET? One of the neat things about this scenario is that I can retouch the XAML sometime later using Sparkle for some eyecandy effects and then run the same app again with no recompilation whatsoever. 

Published 10-04-2006 11:59 PM by smash
Filed under: , , ,

Comments

# re: XAML meets Boo@ Wednesday, October 04, 2006 6:34 PM

Woah, that's neat. With this you can replace you're view quite easily. As long as both views (or xaml files) contain the same components, it should just work.

by jop