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>
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.

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.