5

I have discovered a case where Mvvm Cross EditText binding fails to work correctly when the "Do not keep activities" developer setting is enabled using MvvmCross version 3.5.1. Here are the steps to reproduce:

  1. Create a new Core & Droid project using the "Getting Started" Mvvm Cross packages from NuGet.
  2. Add the ZXing.Net.Mobile PCL component from NuGet.
  3. Implement the ViewModel:

        public class FirstViewModel : MvxViewModel
        {
            private readonly IMobileBarcodeScanner _mobileBarcodeScanner;
    
            public FirstViewModel(IMobileBarcodeScanner mobileBarcodeScanner)
            {
                _mobileBarcodeScanner = mobileBarcodeScanner;
            }
    
            private string _barCode = "";
            public string BarCode
            { 
                get { return _barCode; }
                set { _barCode = value; RaisePropertyChanged(() => BarCode); }
            }
    
            private MvxCommand _scanBarCodeCommand;
            public IMvxCommand ScanBarCodeCommand
            {
                get
                {
                    return _scanBarCodeCommand ?? (_scanBarCodeCommand = new MvxCommand(async () => await OnScanBarCode()));
                }
            }
    
            private async Task OnScanBarCode()
            {
                var result = await _mobileBarcodeScanner.Scan();
                if (result != null && !string.IsNullOrEmpty(result.Text))
                {
                    InvokeOnMainThread(() =>
                    {
                        BarCode = result.Text;
                    });
                }
            }
        }
    
  4. Implement the View:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:local="http://schemas.android.com/apk/res-auto"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
        <EditText
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            local:MvxBind="Text BarCode" />
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Scan"
            local:MvxBind="Click ScanBarCodeCommand" />
    </LinearLayout>
    
  5. Initialize the ZXing.Net.Mobile library in the View:

    [Activity(Label = "View for FirstViewModel")]
    public class FirstView : MvxActivity
    {
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
            SetContentView(Resource.Layout.FirstView);
            MobileBarcodeScanner.Initialize(Application);
        }
    }
    
  6. Run the application and scan a bar code. You can use this Barcodesinc bar code generator and scan from your monitor if you don't have any bar codes handy. The scanned bar code should appear in the EditText.
  7. Edit the View XML by adding an android:id to the EditText.

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:local="http://schemas.android.com/apk/res-auto"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
        <EditText
            android:id="@+id/scan_text"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            local:MvxBind="Text BarCode" />
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Scan"
            local:MvxBind="Click ScanBarCodeCommand" />
    </LinearLayout>
    
  8. Rebuild and run the application. Now the scanned bar code is not displaying in the EditText. The only change was giving the EditText and android:id. Does anyone understand why adding an android:id would break MvvmCross data binding?

Trevor Balcom
  • 3,766
  • 2
  • 32
  • 51
  • 1
    What if you set ScannedBarCode only if the value isn't an empty string ? – Giorgi Aug 20 '15 at 19:16
  • @Giorgi That doesn't change anything. The EditText is still empty on the screen. The ScannedBarCode property still holds the value I scanned. It's like the ViewModel + View are out of sync. I've included an EDIT above that adds more information I've learned since I originally asked the question. – Trevor Balcom Aug 20 '15 at 20:44

1 Answers1

2

The binding is only added for TextEdit and not for EditText. See the implementation here: https://github.com/MvvmCross/MvvmCross/blob/4.0/Cirrious/Cirrious.MvvmCross.Binding.Droid/MvxAndroidBindingBuilder.cs#L85

You could add a custom binding as explained in:

Community
  • 1
  • 1
Martijn00
  • 3,569
  • 3
  • 22
  • 39
  • 5
    `EditText` inherits from `TextView` so it applies for both and binding the `Text` property does work for `EditText`. It is working in multiple of my apps and loads of the samples in MvvmCross-Tutorials. So it is not there the problem lies. – Cheesebaron Aug 21 '15 at 13:32
  • If I just comment out the barcode scanning part, and put in something stupid like ScannedBarCode = "Hello, World" then it updates the EditText on the screen as expected. – Trevor Balcom Aug 21 '15 at 13:48
  • 3
    @Cheesebaron I've figured out how to reproduce this problem. If the EditText has an android:id then the binding fails. If the EditText doesn't have an android:id then the binding works as expected. Do you know what that means? i.e., Am I doing something that is incorrect here, or is it possible this is a bug in MvvmCross binding framework? – Trevor Balcom Aug 21 '15 at 19:56
  • I have have the same exact issue on my side and only in release mode when the static analysis is done. Thank you for point out how to solve it (removing the id). Any idea @Martijn00 ? – Jonathan ANTOINE Jan 25 '17 at 19:43