A Ruby Set in Steel – WPF and IronRuby

work safe

One of the first examples of using IronRuby on the web, possibly the first since it was the announcement of the project, was Scott Guthrie announcing the project and using WPF way back in 2007.

We’ve come a long way since then. But that’s all been internal to IronRuby. In addition, I’ve not seen the community truly embrace IronRuby as it has had some growing pains. I don’t mean to dis those working on the project, just look at my non-existent commit log to see how much of a leg I have to stand on if I where to dis them. I mean to say that I’ve not seen many people talking about using it in production. And until we see production IronRuby, we won’t be able to tell the wider .NET world how awesome working in ruby really is.

Enough groundwork, what’s on today’s menu? I started writing a quick search box for my chat logs at work. I picked up IronRuby, since I loves it so, and threw down some WPF. Then I stood in shock and horror that the commensurate C# code would be much nicer. Here is IronRuby draft one.

Notice the “Left-Side/Right-Side” code. In C#, we fixed this with object initializers. That’s what I want in my code, so I added a method to FrameworkElement to use a hash for initialization. Then I went after how I’m adding stuff to my StackPanels. In Ruby, the idiom to add children is the << operator, so I’ll add that to Panel, the super class for all layout elements. Finally, the explicit aliasing in just crazy talk. Using a namespace is similar to including a ruby Module, so I’ll just include the namespaces I need. And the code got better. I was, in fact, proud of it for a few hours.

Then I started wondering, WPF uses Xaml to be declarative. Can’t I find a way to declare my UI, then add stuff to it? I can write Xaml, can’t I? Well, I can also use Ruby’s XmlBuilder to make xaml look like I’m declaring my UI in ruby. I’ll want to wrap some boilerplate to build the xml with xaml specific things, then turn it into a real CLR window. Then how do I hook up buttons and actions? I can call find_name on a window to find a child with the x:Name attribute. More correctly, I can wrap it with Ruby’s [] operator.

At first blush, it seems like the code is getting bigger, but the Xaml class can be gemmed up and reused. That leaves our application fairly small, which is nice considering it’s a small window. The thing that’s left that’s getting on my nerves is the fact I’m not declaring my click action in the Xaml. Which leads me to the next questions, how do I get Commands and Binding tied in to this? At that point, I’m almost doing this “right”.

Well, I ran some experiments, and here’s what doesn’t work.

  • Data binding doesn’t work. I tried to set a ruby object to a windows DataContext, and the labels didn’t bind.
  • x:Class doesn’t play well with XamlReader.Load(xmlReader). More exactly, I can’t create a class in ruby and expect XamlReader to pick up on it.
  • Adding Click="DoClick" to a button tag causes the XamlReader to blow chunks
  • Trying to add xmlns:l="clr-namespace:Frontal" and rooting the window on l:Lobe, a ruby class in the Frontal module, doesn’t work. XamlReader can’t find the namespace.

No example code, because that would confuse the issue.

I want to get this posted, so I don’t have a solution yet. But I’ve got some ideas percolating. Unfortunately, most of them involve C# run time code generation (code dom), or writing my own WPF builder and bypass the XamlReader all together. I really should take a break from getting WPF “perfect” and start working on using Lucene.NET to do the actual work for my brain in a box.

1 Comment

No Comments

1 Trackback

Leave a Reply

You must be logged in to post a comment.