Search code examples
androidxamarin.androidmvvmcrosscustom-bindingmvxbind

MvvmCross binding to Error property of the TextInputLayout


I'm trying to simplify data validation for one activity which has plenty of controls to be entered (about 10). Every edittext control has a unique validation error so I decided to do with supported by TextInputLayout widget validation. So my layout is below:

<android.support.design.widget.TextInputLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:errorEnabled="true"
    local:MvxBind="Error PhoneNumberError">
    <android.support.design.widget.TextInputEditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        local:MvxBind="Text PhoneNumber" />
</android.support.design.widget.TextInputLayout>

In order to achieve this, I've created a custom binding, pretty simple one:

public class TextInputLayoutErrorBinding : MvxAndroidTargetBinding
{
    public const string TextInputLayoutErrorProperty = "Error";

    public TextInputLayoutErrorBinding(TextInputLayout view) 
        : base(view)
    {
    }

    public override System.Type TargetType
    {
        get { return typeof(string); }
    }

    public override MvxBindingMode DefaultMode
    {
        get { return MvxBindingMode.OneWay; }
    }

    protected override void SetValueImpl(object target, object value)
    {
        var view = (TextInputLayout)target;
        var error = (string)value;
        if (view == null)
            return;

        view.Error = error;
    }
}

and registered it at my Setup.FillTargetFactories

 registry.RegisterCustomBindingFactory<TextInputLayout>(TextInputLayoutErrorBinding.TextInputLayoutErrorProperty, (layout) => new TextInputLayoutErrorBinding(layout));

Unfortunately, when activity is started, my app crashes with the following error:

[mono-rt] Stacktrace:
[mono-rt] 
[mono-rt]   at <unknown> <0xffffffff>
[mono-rt]   at (wrapper managed-to-native) Java.Interop.NativeMethods.java_interop_jnienv_call_nonvirtual_object_method_a (intptr,intptr&,intptr,intptr,intptr,Java.Interop.JniArgumentValue*) <0x00057>
[mono-rt]   at Java.Interop.JniEnvironment/InstanceMethods.CallNonvirtualObjectMethod (Java.Interop.JniObjectReference,Java.Interop.JniObjectReference,Java.Interop.JniMethodInfo,Java.Interop.JniArgumentValue*) [0x00074] in <bd30a18775d94dc8b6263aecd1ca9077>:0
[mono-rt]   at Java.Interop.JniPeerMembers/JniInstanceMethods.InvokeVirtualObjectMethod (string,Java.Interop.IJavaPeerable,Java.Interop.JniArgumentValue*) [0x0005f] in <bd30a18775d94dc8b6263aecd1ca9077>:0
[mono-rt]   at Android.Views.LayoutInflater.Inflate (int,Android.Views.ViewGroup,bool) [0x00061] in <9ab9faae1b4b4f0da28e7c4ac61e2c78>:0
[mono-rt]   at MvvmCross.Binding.Droid.Views.MvxLayoutInflater.Inflate (int,Android.Views.ViewGroup,bool) [0x00042] in <6a0c851a22864d0993089d65320a630c>:0
[mono-rt]   at MvvmCross.Binding.Droid.BindingContext.MvxAndroidBindingContext.CommonInflate (int,Android.Views.ViewGroup,bool) [0x00015] in <6a0c851a22864d0993089d65320a630c>:0
[mono-rt]   at MvvmCross.Binding.Droid.BindingContext.MvxAndroidBindingContext.BindingInflate (int,Android.Views.ViewGroup,bool) [0x00004] in <6a0c851a22864d0993089d65320a630c>:0
[mono-rt]   at MvvmCross.Binding.Droid.BindingContext.MvxAndroidBindingContext.BindingInflate (int,Android.Views.ViewGroup) [0x00004] in <6a0c851a22864d0993089d65320a630c>:0
[mono-rt]   at MvvmCross.Binding.Droid.BindingContext.MvxBindingContextOwnerExtensions.BindingInflate (MvvmCross.Binding.BindingContext.IMvxBindingContextOwner,int,Android.Views.ViewGroup) [0x0000d] in <6a0c851a22864d0993089d65320a630c>:0
[mono-rt]   at MvvmCross.Droid.Support.V7.AppCompat.MvxAppCompatActivity.SetContentView (int) [0x00003] in <76c7f3cdfddd459898d814608e83832e>:0
[mono-rt]   at Android.Views.SignupView.OnCreate (Android.OS.Bundle) [0x00009] in Android/Views/SignupView.cs:17
[mono-rt]   at Android.Support.V4.App.FragmentActivity.n_OnCreate_Landroid_os_Bundle_ (intptr,intptr,intptr) [0x00013] in <6296d3d76c5d4378959a1d9bf7205023>:0
[mono-rt]   at (wrapper dynamic-method) object.47968830-2057-4cdb-aa78-9844556333c4 (intptr,intptr,intptr) [0x00017] in <3fd174ff54b146228c505f23cf75ce71>:0
[mono-rt]   at (wrapper native-to-managed) object.47968830-2057-4cdb-aa78-9844556333c4 (intptr,intptr,intptr) [0x00022] in <3fd174ff54b146228c505f23cf75ce71>:0

Can I achieve my goal with the binding to validation errors or I have to do it manually?


Solution

  • I turned out that Xamarin has Error property and you can bind to it even without any custom bindings. Just like this:

    local:MvxBind="Error PhoneNumberError"