Last time, I showed how to connect a Ruby class to a VB class using RubyCLR bi-directionally. This time, we use Ruby to connect to a VB form and display data in .NET. We'll also write our event handlers in Ruby, just for kicks.
I've attached a zip file that contains the Ruby scripts and the VB project.
Because it's a sample "project", the user experience may not be very fine-tuned. Also, I'm not convinced that people will use this paradigm to interact with Delicious. Basically there are three scripts in the sample project; one script will download your delicious bookmarks and store it locally in an XML file. This is "get.rb". The second script, "find.rb", will search through the XML based on tags of your choice. These two scripts are interesting only if you're interested in Ruby; they don't interact with Visual Basic in any way. The final script, "ss.rb", will search through the XML based on the tags of your choice like "find.rb", but it will return the results in a form created from VB, allowing you to select the URL that matches your search criteria, and will launch your web browser with the requested URL.
Since I'm talking mainly about Ruby and Visual Basic interaction through RubyCLR, I won't go into detail about how the first two Ruby scripts work. There are tons of web sites out there that do a much better job then I.
The first thing that we need to do is to create a blank form that has the necessary controls. This is pretty standard .NET stuff, so I won't go into detail, but suffice to say that we have a standard list box control to display URLs and we have an OK and a CANCEL button. To use RubyCLR, you need to build either a .exe or a .dll; RubyCLR doesn't actually instantiate your exe if you reference it from Ruby, but it does know how to load types from both DLLs and EXEs, which is nice. The only code I have in Visual Basic is to muck around with the table layout control. Everything else will be driven by Ruby.
To get the form instantiated, it's simply a matter of calling new on the form. However, it may be beneficial to contain the .NET form within a Ruby class to abstract it away; purely up to you, but if you look at ss.rb, you will see that I followed the same pattern John uses and created a MainForm Ruby class which encapsulates the .NET form (Deliciousui::MainForm.new).
In the constructor, you will see that I have hooked up three event handlers. Here's the handler for the SelectedIndexChanged event of the list box:
form.ListBox.SelectedIndexChanged do |sender, args| form.ButtonGo.Enabled = true if form.ListBox.SelectedItem != nilend
This is where using RubyCLR is so cool; I can assign and define my event handlers within the same "locality of code" - ie, I don't need to define a private method, and then assign that method to the delegate handler. This is one of the reasons why I like the way Ruby blocks work; it places all the code to do something at the same location.
The current build of RubyCLR takes a form type and instantiates it for you. In order to get this app to work, I had to make a change in WinFormsApp.rb (look in your RubyCLR installation directory) to allow you to pass in an instantiated form. With this change, the following code instantiates a form:
WinFormsApp.setupfrm = MainForm.newfrm.results = resultsfrm.initialize_list()WinFormsApp.runex( frm.form )
Note: The changes that I made have not been sanctioned by John. I've told him about this change and he knows about it, but I believe he's working on refactoring some of the core code right now. Keep an eye out on the RubyCLR site to keep abreast of the latest status. In the mean time, I've attached the modifications I've made to WinFormsApp.rb to this post.
I've attached the sample to this blog post. Try it out! Being able to hook up Ruby with VB is a really cool thing. I totally believe that .NET is enabling some amazing scenarios: being able to inter-change C++/CLI, C#, VB, and now Ruby (among other languages) can really make all programmers' lives easier by allowing us to use the right tool for the job.