WPF Metaclass
From IronPython Cookbook
If you prefer to write an WPF application in a class, this is a metaclass that makes it easy to access controls, somewhat like waddle in XAML_GUI_Events_Example. Look at the code and comments at the bottom to see what it does.
Here's the metaclass code (and let's say you save it as WPFUIElements.py)
import clr
clr.AddReference("PresentationFramework")
clr.AddReference("PresentationCore")
from System.Windows import UIElement, LogicalTreeHelper
class WPFClass(type):
def __new__(meta,classname,bases,classDict):
def __gettreechildren__(control,classDict):
for item in LogicalTreeHelper.GetChildren(control):
if hasattr(item,"Name"):
if item.Name:
classDict[item.Name] = classDict["_xaml"].FindName(item.Name)
if isinstance(item, UIElement):
classDict = __gettreechildren__(item,classDict)
return classDict
if "_xaml" in classDict.keys():
classDict = __gettreechildren__(classDict["_xaml"],classDict)
return type.__new__(meta,classname,bases,classDict)
else:
raise Exception("""Please define a _xaml attribute, example:
class Main(Application):
__metaclass__ = WPFClass
_xaml = XamlReader.Load(XmlReader.Create(FileStream("main.xaml",FileMode.Open)))""")
Now here's the xaml (saving it as main.xaml, in the same folder):
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Name="Window"
Title="MainWindow"
Width="640" Height="480" mc:Ignorable="d">
<Window.Resources>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="FontFamily" Value="Trebuchet MS"/>
<Setter Property="FontSize" Value="13.333"/>
</Style>
</Window.Resources>
<Grid x:Name="LayoutRoot">
<Menu VerticalAlignment="Top" Height="22">
<MenuItem x:Name="file_menuitem" Header="File" FontFamily="Trebuchet MS" FontSize="13.333">
<MenuItem x:Name="new_menuitem" Header="New"/>
<MenuItem x:Name="open_menuitem" Header="Open"/>
</MenuItem>
</Menu>
</Grid>
</Window>
Now here's the main file, in the same folder as the other two files:
import clr
clr.AddReference("PresentationFramework")
clr.AddReference("PresentationCore")
clr.AddReference("System.Xml")
from System.Windows import Application
from System.Windows.Markup import XamlReader
from System.IO import FileStream, FileMode
from System.Xml import XmlReader
from WPFUIElements import WPFClass
class Main(Application):
__metaclass__ = WPFClass
_xaml = XamlReader.Load(XmlReader.Create(FileStream("main.xaml",FileMode.Open)))
def __init__(self):
pass
def run(self):
self.open_menuitem.Header = "Open File"
#instead of self._xaml.FindName("open_menuitem").Header = "Open File"
self.new_menuitem.Header = "New File"
#instead of self._xaml.FindName("new_menuitem").Header = "New File"
self.Run(self._xaml)
Main().run()
This is made obsolete in IronPython 2.7A, where there is clr.LoadComponent to do the same thing and more.

