DCSIMG
You are reading a MIX Online Opinion. In which we speak our minds. hanshu Meet Hans Arrow

Opinion

0Comment Retweet

Writing a UserControl in Python

Jul 31, 2009 In Development By Hans Hugli

While putting together samples for Gestalt, I found that I could save a vast amount of time creating a control’s UI using XAML (XML Application Markup Language) as opposed to spending time to generate it programmatically. It’s not only time consuming creating it in verbose code, but it forces you to spend time getting to understand the nuances of XAML-to-code translation.

Incidentally, in case you are not familiar with Gestalt, it is a javascript that you can add to your web pages, which enables web developers to write rich web applications without the need of an Integrated Development Environment. Now you can write RIA applications using only XAML, and Python or Ruby! Behind the scenes Gestalt uses Silverlight to generate the UI.

I’m going to examine the code for the Advanced Trigonometry sample to see how we employed UserControls to create “Node” objects.

A fairly elegant approach to accomplishing this task is to create a typical XAML file and load it using the .Net XamlParser class. We download the XAML file using the .Net WebClient class, which returns it as a string. In the sample’s initialization we begin the process of creating our “Node” UserControl by first calling:

client = WebClient() 
client.DownloadStringCompleted += NodeLoaded 
client.DownloadStringAsync(Uri("node.xaml", 
     UriKind.Relative)) 

When the XAML has been downloaded as a string, the NodeLoaded event fires. In the NodeLoaded method the string is cached in the _node variable.

def NodeLoaded(sender, e): 
   global _node 
   _node = e.Result 

Before I move on, we need to take a look at the Node class which inherits from UserControl (inside the parens means inheritance in Python) and takes a string, xaml, as a parameter. The CreateObject method calls the XamlReader.Load method. This method accepts a string and generates an object graph. The Content assignment makes the call to the CreateObject method and assigns the generated object graph to the UserControl’s inherent Content property.

class Node(UserControl): 
   def __init__(self, xaml): 
      self.xaml = xaml 
   def CreateObject(value): 
      return XamlReader.Load(value) 
   self.Content = CreateObject(self.xaml) 

Now the UserControl can be created. The Main() method calls:

n = Node(_node)

which passes in the Node.xaml contents as a string, and in turn creates a Node instance. To access any of the XAML elements in the XAML they need to be accessed via the Content property, like so:

n.Content.MyXamlElement.MyXamlElementProperty = somevalue

Another very useful thing to know is how the create Python properties in classes, there are many approaches. This is the basic approach I took in the Python 2.6 implementation that the DLR uses. In the class definition you must create two methods and refer to them in a call to the property method. If added to the above Node class, the following fragment would update the node’s Left position when the X property of the node is set, and return its Left position when retrieved.

   ### X property ### 
   def SetX(self, value): 
      self.SetValue(Canvas.LeftProperty, 
         Convert.ToDouble(value)) 
   def GetX(self): 
      return self.GetValue(Canvas.LeftProperty) 
   X = property(GetX, SetX)

Finally, assign the Text property of one of the Node’s XAML elements, and add the created node to a “nodes” Canvas, specified in the main application xaml, like so:

n.Content.display.Text = "I am a node"
nodes.Children.Add(n)

Knowing how to create a UserControl in Python with Gestalt, greatly increases productivity, and you can start putting together some very robust applications now. You should know that these UserControls cannot be directly referenced in any XAML since the XAML would need to contain assembly references to your custom UserControls. Today there is no built in support for this scenario, but to work around this, simply add UserControls to XAML elements programmatically.

Note that this sample depends on being served off a web server since it is utilizing the WebClient and so will not work on the local machine alone. The source to this entire sample (including the XAML files) is available here.

If you have a comment, or if you have an even cleaner approach that eliminates the need for accessing XAML elements via the Content property, please do  not hesitate to leave a comment Leave a comment, and if twitter is your thing, follow us.

Follow the Conversation

0 Comments so far. You should leave one, too.

Add your social network profile — we’ll use it to find your avatar. Or, just add your email. That works too.