Thursday, June 20, 2013

Tibet Binding

Today, I'd like to share an early preview of some new MvvmCross work - especially to ask whether people feel it is a feature they will want, and whether anyone has any further requirements, ideas or code they'd like to contribute.


This new work all applies within the heart of MvvmCross data-binding. As many of you know, earlier this year we rewrote the binding engine in MvvmCross to use the simpler, cleaner 'Swiss' binding. More recently, we've now been working hard to extend this clean 'Swiss' syntax in some new directions - and this work is codenamed Tibet



Some of the motivation behind Tibet was the work we've already done, but beyond that we've also received some really valuable ideas and input from users and from community comments, including blog posts like "Knockout - what Mvvm should have been like in Xaml"


We hope that the output of Tibet will allow us to databind to viewmodels using a richer syntax including:

  1. Function-like value converter calling
  2. Multi-bindings - allowing a single UI field to update in response to any of several ViewModel property changes
  3. The use of literals (ints, doubles, booleans and strings) within the bindings.
  4. Simple operator syntax which can be applied across multi-bindings - note that these operations are *not* full .Net operators - instead they just provide a simple interpreter
  5. Nested application of operators and value converters - allowing you to use multiple bindings and multiple value converters within the same binding expression.
  6. The unification of binding so that the same engine and syntax is used across all platforms (across all of Windows, Android and iOS)

As an example of the syntax we can build, I've recorded this short introduction:



Within this introduction we build up to a 'complicated' and 'artificial' binding of:

    Text Salutation(Counter + Length(Hello)) + ' ' + Hello


This binding says that the value of Text should be dynamically calculated by:
  1. applying the LengthValueConverter to the Hello property
  2. adding the value of the Counter property
  3. applying the SalutationValueConverter to that sum
  4. concatenating the resulting string with a single space 
  5. concatenating the resulting string with the value of the Hello property

The basis for this demo code today is a simple ViewModel and 2 simple ValueConverters:



The binding in Android then looks like:



The binding within iOS is similar. Note that we don't yet use the Fluent binding for this new binding, although we would hope to add some fluent code for it in the future:



The binding within Windows is:




I've pushed the code for this first demo to: https://github.com/slodge/Tibet



That's all there is for now.

As I said at the start this is an early preview of a new idea, and I'm especially interested to hear:
  • whether it's worthwhile continuing... 
  • whether anyone has any further requirements, ideas or code they'd like to contribute. 

Please do let me know if you have any comments :)

6 comments:

  1. For me when you start doing complex binding statements like

    Text Salutation(Counter + Length(Hello)) + ' ' + Hello"

    I would prefer it to be a property in the viewmodel (if they are platform independent bindings)

    This will keep the view(s) as dumb as possible with no logic – that aside it’s really neat and I can see being a useful option certainly seems a more natural way of expressing bindings.

    ReplyDelete
  2. local:MvxBind="Text Salutation(Counter + Length(Hello)) + ' ' + Hello"

    Reminds some nice features of Caliburn.Micro

    I'm used this for my WinPhone application.
    "cal:Message.Attach" with $params was very very easy in usability :)

    ReplyDelete
  3. Hello!

    First of all, I have to say that the binding stuff is really one of the most important things which would be waiting for some improvements in MvvmCross. Despite of my own oppinion that binding generally must not provide very reach functionality (as that would indicate something is not designed well), there are several small things which I am suffering of pretty much.

    I must completely agree with asudbury. Such way to manage binding (with the sample with strings concatenation) just looks like a little bit model-driven approach replacement. (Especially, if the binding is the same through all the platforms). Plus, it would bring additional complecity into the binding syntax.

    For me personally, the things which MvvmCross binding lacks the most at the moment are:

    - formatting. (for instance, with numbers). That's ok to create some Field "FullName" in viewModel to combine "FirstName" and "LastName", for instance, (as adudbury says) but that does not sound pretty convenient also to create a field "SallaryFormatted" just for databinding. So, in that sense, the old ASP.NET databinding approach looks great for me: Sallary.ToString("{0:0.00}"). For example: .Bind().Format("{0:0.00}s")
    Another option here might be adding Attributes to ViewModel properties for simple cases, like [OutputFormat("{0:n}")] or just [OutputFormat("n")].
    This thing might be also very useful for developers who uses localization.

    - simple types converting and logical operators (n. 3, 4 and (probably) 5 mentioned by you). "Length(Hello)" is one of the things. But also, something like "Hidden Length(Hello) == 0" or "BackgroundColor IsExists ? UIColor.Green : UIColor.Red" (which is actually, a sample of actually platform/dependent binding, what might be very usefuly). That's pretty unconvenient to create Converters for such tiny situations. Especially, if you want for different views to have a little bit another colors: "BackgroundColor IsExists ? UIColor.White : UIColor.Black" (you should then create BoolToColorUserConverter or BoolToColorUserInVacationConverter etc).


    ...and I am not sure I fully get if the following really needed though:
    - Multi-bindings. It seems dragging responsibility out of ViewModel to view. (This is actually, the same talk about viewModel properties concatenation. As if it exists, then such feature needed of course, if not - then not). But generally that's the thing asudbury mentioning.

    Thanks!

    ReplyDelete
  4. MVVM for me is a way to write platform independent code. Any time I have to place any logic into View, it's duplication of effort between different platforms. For that reason, I avoid logic in views at any cost. The presented example is something that I'd prefer doing in the ViewModel as a readonly property and binding to that property.

    +1 to asudbury

    ReplyDelete
  5. I agree with Boreslav that it would be great to see formatting added.

    ReplyDelete