I am new to MVVMCross (and mobile in general) and I am looking to implement binding to error messages (like FluentValidation ValidationResults or IDataErrorInfo).
Preferably, I would like an Errors like dictionary that I can bind directly to:
bind(label).To(vm => vm.Errors["Name"])
I have tried an ObservableDictionary (http://blogs.microsoft.co.il/blogs/shimmy/archive/2010/12/26/observabledictionary-lt-tkey-tvalue-gt-c.aspx), but I am not getting notified when the ViewModel adds errors.
As expected, wrapping access as a property in the view model works, but could get cumbersome:
public string NameError { get { return Errors.ContainsKey("Name") ? Errors["Name"] : null; } }
I have also considered creating a custom binding, but am not sure how to get access to the ViewModel and pass the field name I want. Seems like I could pass Errors or the property name.
Finally, since invalid conversions (i,e. 22ab for an int) are not pushed down into the view model, is there a way to get those errors? Should I be validating before data gets pushed back to the view model instead? Like textFieldShouldEndEditing or ShouldChangeCharacters on iOS? I could wrap a custom control if necessary.
What techniques are others using with Xamarin/MVVMCross using to provide validation feedback?
Thanks in advance.
MvvmCross doesn't currently implement the IDataErrorInfo level of data-binding
This is mainly because no-one has yet asked for it - but I guess that might just change with this question. If you do have specific requirements, then the project would be interested to hear them - suspect the best place for that is github issues for the project.
For your specific questions...
The approach of binding to an ObservableDictionary which implements the INotifyCollectionChanged and INotifyPropertyChanged should work.
However, looking at the code in your link, I don't think that dictionary is correctly implementing INotifyPropertyChanged - in addition to the INotifyCollectionChanged events, it should also be raising the property change notifications on Count and Item[] - without these the binding to the whole set will work, but not to individual items and to count. For an example source of ObservableCollection, see https://github.com/mosa/Mono-Class-Libraries/blob/master/mcs/class/System/System.Collections.ObjectModel/ObservableCollection.cs
Looking a second time at the code in your link, it appears that the dictionary is correctly implementing INotifyPropertyChanged - it is raising the property change notifications Item[] - and this is the string required for the individual items to bind. Do you have debug trace enabled? Does the trace give you any clue about why it is failing?
I've submitted some fixes today - https://github.com/slodge/MvvmCross/issues/345 - and have tested them in this sample - Test_WithErrors.axml - I would expect this same sample should work on iOS (the iOS test app is a work in progress) and that it should also be extensible for Jeremy's excellent FluentValidation (although I've not used that in PCL form yet)
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Enter email:"
/>
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="30dp"
local:MvxBind="Text Email"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#ff0000"
local:MvxBind="Text Errors['Email']"
/>
Thanks for pointing out this error - fixed binaries will be nuget in the next day or two!
On the int-string question, the binding layer currently "does it's best" (TM) to convert UI types to VM types. However, there is no event currently triggered when it fails - so there is no way to fire any validation rules in the ViewModel from the binding.
Instead, where free text input is allowed, I think you'll need to implement the ViewModel types as string and will then need to trigger the validation rules when the ViewModel property changes. Because MvvmCross doesn't expose any binding level hooks for when validation occurs, you'll maybe need to tweak when binding occurs (e.g. on first responder resign) rather than having continual validation - but this should be fairly straight-forward using a custom-binding.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With