Silverlight vs. JavaFX

From no name for this wiki
Jump to: navigation, search

Data binding

One big thing for RIA applications is databinding. Example: There is a textbox on a form and it's content is bound to a model:

The Model:

 Model model = new Model();
 ...
 public class Model {
   public String name;
 }

The GUI-Element:

 TextBox box = new TextBox();
 box.text = model.name;

What you need is the following behaviour:

  • When the user changes the value in the textbox, the value must be written to the property name of the object model.
  • The value of the property name of object model must be displayed in the textbox.

C# and Java don't support this pattern in a neat way. You have to write an observer - observable pattern. Eventually you have to add code to the textboxValueChanged event.

 public void onValueChangedTextBox()
 {
   model.name = box.text;
 }

In windows forms you can use bindings:

 this.box.DataBindings.Add("Text", model, "Name");

and

public class Model: INotifyPropertyChanged
{
  public event PropertyChangedEventHandler PropertyChanged;

  private string name;
  public string Name
  {
    get { return name; }
    set
    {
      name = value;
      if (this.PropertyChanged != null)
      {
        PropertyChangedEventArgs args = new PropertyChangedEventArgs("Name");
        PropertyChanged(this, args);
      }
    }
  }
}

The programmer should not be concerned with such thins like INotifyPropertyChanged (this is a bit subjective, I know that).

The javaFx way

The force in javaFX lies in exactly this binding. The bidning is integrated into the language. There are some keywords bind and bind with inverse. The second is a bidirectional binding.

  box = TextBox {
         layoutX: 180
         layoutY: 80
         text:   bind model.name with inverse;
       }

The model looks like this:

public class Model {
    
    public var name: String = "Some init val";
}

There are some limitations, though. What is missing is the direction from ui to model. I don't know how to tell javafx that I want an uni-directional binding from the ui to the model (I am no javafx crack).

One other limitation is that bindings must be to properties of defs (instead of var) objects. Defs are some kind of constants. Only a warning is displayed by the compiler, so it is not a big issue.

The silverlight way

In silverlight, there is no new langage, so the INotifyPropertyChanged must still be implemented. The DataContext is one way to publish the model:

this.box.DataContext = model;

And then bind to a property in xaml:

<TextBox Text="{Binding Mode=TwoWay, Path=Name}"/>

What is very cool in Silverlight is its tremenduous options with bindings. This tells silverlight that I want to update the binding by explicit code:

<TextBox Text="{Binding Mode=TwoWay, Path=Name, UpdateSourceTrigger=Explicit}">

Or I can store the model in a global resource section such as app.xaml.

<Application.Resources>
        <tm:Model x:Key="model"/>
    </Application.Resources>

and then

  <TextBox Text="{Binding Source={StaticResource model} Path=Name}"/>

This is all very nice. The downside is the language C#. To make all this possible some infrasturcture in self made controls is needed:

public class SomeControl : UserControl
  public static readonly DependencyProperty TextProperty;

  static SomeControl () {
      PropertyChangedCallback callback = new PropertyChangedCallback(PropertyChangedCallback);
      PropertyMetadata metadata =
             new PropertyMetadata(callback);
      TextProperty = DependencyProperty.Register("Text",
                   typeof(string),
                   typeof(SomeControl),
                   metadata);
  }

  public static void PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
  {
     ...
  }
.....

asynchronous operations

Another big thing in ui-programming is multithreading. You don't want to freeze your UI while it is downloading some stuff with webservices.

the java-fx way

To be short, it is cumbersome(subjective, I know). java-fx is missing helper code here. I don't understand why such an important thing is missing. Here is some overview of how you achieve multi-threading just to show how much code has to be written. But to be honest, this code can be reused and is written only once.

1. Create a java class RF and an interface Runnable2.

public interface Runnable2 {
    public Object run();
    public void completed(Object p);
}

public class RF implements RunnableFuture {

    Runnable2 runnable;

    public RF(Runnable2 rable2)
    {
        this.runnable = rable2;
    }

    @Override
    public void run() throws Exception {
        Object result = runnable.run();
        postMessage(result);
    }

    public void postMessage(final Object msg) {
        Entry.deferAction(new Runnable() {
            public void run() {
                runnable.completed(msg);
            }
        });
    }
}

2. Then you need some javafx helper class:

public class MTask extends JavaTaskBase, Runnable2 {

    public  def  wsClient = WebserviceClient {};

    override public function completed (arg0 : Object) : Void {
        throw new UnsupportedOperationException('Please implement in subclass');
    }

    override public function run () : Object {
        throw new UnsupportedOperationException('Please implement in subclass');
    }

    override protected function create () : RunnableFuture {
        new RF(this);
    }

    postinit {
        start();
   }

}

And now you can use it in the gui. Bind your UI-elements to the view-model.

MTask {

 override public function run () : Object {
    wsClient.testInfo();
 }

 override public function completed (arg0 : Object) : Void {
   var testTO = arg0 as TestTO;
   model.testTitle = testTO.getTitle();
 }            
}

//bind ui to model
Label {
  layoutX: 150
  layoutY: 20
  text: bind model.testTitle;
}

the silverlight way

Calling webservices asynchronously is the default in Silverlight. Service references in SL-projects won't let you call webservices synchronously (this is a feature missing in SL).

Here is a sample. Client is a webservice proxy class.

To do a webservice call you first register a handler which is called when the call is complete:

Client.GetTestInfoCompleted += new EventHandler<GetTestInfoCompletedEventArgs1>(GetTestInfoHandler);

Then you call it:

Client.GetTestInfoAsync(AuthToken, TestResultId);

The handler:

public void GetTestInfoHandler(object sender, GetTestInfoCompletedEventArgs1 args)
{
  if (this.CheckForCommError("GetTestInfoHandler", args))
  {
       return;
  }
  TestTO to = (TestTO)args.Result;
  this.testInfo.SetTestInfo(to);//update the view-model.  
}

This pattern could be easely integrated into javafx. Bad thing that you have to do it yourself.

Formatted Text

Silverlight has the ability to display rich text with the TextBlock control. Javafx is missing such a control completely. Font and style can be set only for the whole text. A TextBlock like control is planned for javafx2. What you can do in JavaFx to circumvent the problem is integrating swing compoments into javafx. Swing has been around for a while now, so you can expect a solution to many ui-problem.

Libraries

Somehow it is not correct to compare JavaFX and Silverlight. JavaFX has better to be compared with Windows Presentation Framework Browser Applications (XBAP). In XBAP the whole .net Framework stack without restrictions is ready to use. On the other hand, XBAP runs only on windows (not mac, not linux (not even mono)).

But in JavaFX you can use almost any java library on any platform.