2
votes

I'm using the fluent syntax and lambdas for data binding in MvvmCross. An example of this is:

var bindings = this.CreateBindingSet<MyTableCell, MyTableCellViewModel>();
bindings.Bind(titleLabel).To(vm => vm.MY_TITLE);
bindings.Apply();

Whenever I try this with an underscore in a view model property I get an exception:

Cirrious.CrossCore.Exceptions.MvxException: Unexpected character _ at position 3 in targetProperty text MY_TITLE

I believe the error message is a result of MvvmCross parsing the data binding, yet this seems to only make sense for people using string-based data binding, not the lambda expression syntax.

Unfortunately, I cannot change the view models so I'm looking for a workaround to allow underscores in the view models. Any ideas?

1

1 Answers

2
votes

I'd guess this is a general problem in the MvvmCross parser - probably in

    private void ParsePropertyName()
    {
        var propertyText = new StringBuilder();
        while (!IsComplete && char.IsLetterOrDigit(CurrentChar))
        {
            propertyText.Append(CurrentChar);
            MoveNext();
        }

        var text = propertyText.ToString();
        CurrentTokens.Add(new MvxPropertyNamePropertyToken(text));
    }

In https://github.com/MvvmCross/MvvmCross/blob/v3/Cirrious/Cirrious.MvvmCross.Binding/Parse/PropertyPath/MvxSourcePropertyPathParser.cs#L80

Which probably needs to be fixed to something like:

        while (!IsComplete && 
               (char.IsLetterOrDigit(CurrentChar) || CurrentChar == '_')

There are workarounds you could do, but the easiest solution is probably to fix this and rebuild, rather than to try workarounds.


But if you do want to try workarounds....

Assuming this is static (non-changing) text and this is just a one-off for now, then one workaround might be to add a property to your cell called Hack and to then bind like:

 bindings.Bind(this).For(v => v.Hack).To(vm => vm);

 //...

 private MyTableCellViewModel _hack;
 public MyTableCellViewModel Hack
 {
    get { return _hack; }
    set { _hack = value; if (_hack != null) titleLabel.Text = _hack.MY_VALUE; }
 }

Another alternative (with the same assumptions) might be to use a value converter -

 bindings.Bind(titleLabel).To(vm => vm.MY_TITLE).WithConversion(new WorkaroundConverter(), null);

 // ...

 public class WorkaroundConverter : MvxValueConverter<MyTableCellViewModel, string>
 {
     protected override string Convert(MyTableCellViewModel vm, /*...*/)
     {
         if (vm == null) return null;
         return vm.MY_TITLE;
     }
 }