Binding ruby objects

Jun 12, 2008 at 1:26 PM
Hello!
Am not sure, is it right place for my problem, but will try anyway.
I am learning ruby/silverlight binding. I can bind whole variable to TextBlock, but I am unable to get it working with variable property
This is my source, app.rb:

require "Silverlight"
include System::Windows::Data
include System::ComponentModel

class App < SilverlightApplication
  use_xaml
  attr_accessor :xdata

  def binding1
    xdata="Binding app variable @xdata using attr_accessor"
   
    bn=System::Windows::Data::Binding.new ""
    bn.source=xdata
    bn.mode=BindingMode.TwoWay
    debug_txt.set_binding TextBlock.TextProperty, bn
  end

  def binding3
    md=MyData.new
    md.data="Binding property of complex variable"
       
    bn=System::Windows::Data::Binding.new ""
    bn.source=md
    bn.path=PropertyPath.new "data"
    bn.mode=BindingMode.TwoWay
    debug_txt.set_binding TextBlock.TextProperty, bn
  end

  def initialize
    binding3
  end
end

class MyData
    attr_accessor :data
end

App.new

In xaml file only one TextBlock required named debug_txt.
While binding1 will work, binding3 not in Silverlight 2b2 (using sdl-sdk 2b2 also).
Is it a bug or I am doing something wrong?
Also, very interesting topic for me is implementing INotifyPropertyChanged interface in ruby. Does anybody tried it? How it can be done, is C# object must has event of PropertyChangedEventHandler type and fire this event each time binded data changed.

Thanks!



Oct 27, 2008 at 1:27 PM
I'm having a similar problem. I've got a Person class created like this:

class Person
   attr_accessor :name, :age

   def initialize(name, age)
      @name, @age = name, age
   end
end

When I set the data context of a textblock to an instance of Person and then set the text property to {Binding}, I can see that the object is of type "IronRuby.Builtins.RubyObject". The problem is when I set the path of the binding to :name or name , I get nothing. The binding does not appear to work. Does anybody know the appropriate syntax for binding to members of Ruby objects?
Nov 1, 2008 at 12:53 AM
My understanding is that databinding doesn't at this stage work for ruby classes because the xaml data binding uses reflection to find the property on the bound object as well to determine whether it implements the INotifyPropertyChanged interface.  Ruby objects do not look like compiled objects at this stage as far as reflection is concerned.

Can someone else confirm that this supposition is correct?

What you can do is create a basic C# object with the IPropertyNotify interface but then add additional methods to the class in ruby for firing the property changed event and whatever other business logic you want- it's a bit awkward but still more succinct than pure C# equivalent.
Coordinator
Nov 1, 2008 at 1:22 AM
Yep, Ruby objects aren't true CLR objects, except in certain cases where we've already done the .NET interop work. We focused on making the language work first, and then .NET interop after. We're passing language tests in the 90% range, and library tests at almost 80%, so getting the language working is almost done. :)

This issue is the same reason why you can't make a Ruby Silverlight app that looks like this:

# page.rb
include System::Windows
include System::Windows::Controls
class Page < UserControl
def initialize
Application.current.load_root_visual(self, "page.xaml")
end
end

<!-- page.xaml -->
<UserControl x:Class="Page">
...
</UserControl>

The "self" passed into load_root_visual will be a Ruby type, and the x:Class attribute won't be able to find the "Page" object, since it'll be looking for a CLR type. We do make a CLR Type under the covers for "Page", but it's got a auto-generated name. We need to do the work to make that CLR type the same name.

So, for now, you'll need a C# class to get databinding to work, but hopefully this should start working correctly when we do the .NET interop work.

~Jimmy
Coordinator
Nov 5, 2008 at 8:30 PM
Edited Nov 5, 2008 at 8:31 PM
@igors To be more clear, you're example is expected not to work, because of this line:

bn.path=PropertyPath.new "data"

The binding has no idea how to access "data", since it's just a method on your Ruby object, and it will look for a CLR "Property" on the type you give it. As a work-around, you'll have to bind directly to variables in scope, rather than setting the Binding path. This is something I'm looking to fix with the .NET interop work.

~js