Is it possible to have method binding in mvvmcross using Fluent API?

fluent, mvvm, mvvmcross, xamarin

Solution

Is it possible to...

Yes, MvvmCross is very extensible so you could add this if you wanted to.

To do it, you'd need to:

- give this scheme a name of some kind - for convenience now, let's call it Amit-Binding as Method-Binding has already been used for Auto-ICommand binding - see N=36 in http://mvvmcross.wordpress.com

- work out it's spec a little more fully - e.g. just clarifying how changes will be published from the ViewModel

- work out how the Amit-binding will be presented in binding descriptions - and probably best to work out how to present them in text-format bindings too

- provide one or more extension methods which allow the FluentBinding to generate a binding description containing an Amit-Binding - this will involve parsing the Expressions using your generic parameterised method calls

- possibly also extend the Tibet binding parser and the source property parser classes to allow it to parse the text format of these Amit-bindings (this may not be necessary if you've chosen an already-parseable format for the text version of these classes)

- provide a source property binding extension factory which will know when and how to create these Amit-Source bindings.

This may sound like a lot of effort - but it is actually quite doable. For an example of how `INotifyChanged` source binding has been added using a plugin, see https://github.com/slodge/MvvmCross/tree/v3/Plugins/Cirrious/FieldBinding/Cirrious.MvvmCross.Plugins.FieldBinding - although note that this was achieved without adding any new requirements to FluentBinding or to the parsers.

Alternatively...

You could just use string-indexer binding on "normal properties" or on fields (if using the FieldBinding plugin).

For an example of this in both Touch and Droid, see the ObservableDictionary example in https://github.com/slodge/MvvmCross-Tutorials/tree/master/ApiExamples

the Core project includes an ObservableDictionary implementation reproduced from http://blogs.microsoft.co.il/blogs/shimmy/archive/2010/12/26/observabledictionary-lt-tkey-tvalue-gt-c.aspx (normal Dictionaries can be used if dynamic updating isn't required)

the Touch UI project includes a fluent binding block of:

    var set = this.CreateBindingSet<ObservableDictionaryView, ObservableDictionaryViewModel>();
    set.Bind(label1).To(vm => vm.Items["One"]);
    set.Bind(label2).To(vm => vm.Items["Two"]);
    set.Bind(label3).To(vm => vm.Items["Three"]);
    set.Bind(all).To(vm => vm.ReplaceAllCommand);
    set.Bind(each).To(vm => vm.ReplaceEachCommand);
    set.Bind(makeNull).To(vm => vm.MakeNullCommand);
    set.Apply();

Problem

I have an object structure that looks like this. ``` public class Model : MvxViewModel { private IDictionary<string, string> _properties; public IDictionary<string, string> Properties { get { return _properties; } } public string this[string key] { get { return Get(key); } set { Set(key, value); ;} } public Model() { this._properties = new Dictionary<string, string>(); } public void Set(string propertyName, string value) { if (!_properties.ContainsKey(propertyName)) { _properties[propertyName].Value = value; } } public string Get(string propertyName) { return _properties[propertyName]; } } ``` I need to bind information from this object to a control using Fluent API. My control is create in the code. The code looks like this: ``` protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); SetContentView(Resource.Layout.Hello); Model employeeModel = new Model(); model["Id"] = 1000; model["FirstName"] = "Stuart"; model["MiddleName"] = ""; model["LastName"] = "Lodge"; TableLayout containerLayout = this.FindViewById<TableLayout>(Resource.Id.containerLayout); if (containerLayout != null) { TableRow newRow = new TableRow(base.ApplicationContext); newRow.SetMinimumHeight(50); var txtFirstName = new EditText(ApplicationContext); txtFirstName.Hint = "First Name"; var bindingSet = this.CreateBindingSet<HelloView, Model>(); bindingSet.Bind(txtFirstName).For("Text").To(vm => vm.Get("FirstName")); bindingSet.Apply(); newRow.AddView(txtFirstName); containerLayout.AddView(newRow); } } ``` Is it possible to do something like this?

Original source