Jam*_*mer 10 validation mvvm mvvmcross xamarin
我正在构建我的第一个Xamarin MvvmCross应用程序,目前我正在考虑验证用户对视图模型的输入.
对这个插件进行大量搜索(包括MvvmCross团队)链接:
这个插件使用了很老版本的MvvmCross v3.我已经尝试从这个插件中获取代码并将其直接构建到我的应用程序Core项目中,直到我遇到Bindings的变化.然后我得出结论,这个插件实际上需要完全重写,因为这样才能使用最新版本的MvvmCross.
所以我现在有点卡住了.
目前推荐的在视图模型中执行输入验证的最佳方法是什么?
Kil*_*man 28
编辑:在GitHub上添加示例项目 https://github.com/kiliman/mvx-samples/tree/master/MvxSamples.Validation
我使用MVVM验证助手http://www.nuget.org/packages/MvvmValidation/
这是一个易于使用的简单验证库.它与MvvmCross无关.
这是我如何使用它,例如,在我的SigninViewModel中:
private async void DoSignin()
{
try
{
if (!Validate())
{
return;
}
IsBusy = true;
Result = "";
var success = await SigninService.SigninAsync(Email, Password);
if (success)
{
Result = "";
ShowViewModel<HomeViewModel>();
Close();
return;
}
Result = "Invalid email/password. Please try again.";
}
catch (Exception ex)
{
Result = "Error occured during sign in.";
Mvx.Error(ex.ToString());
}
finally
{
IsBusy = false;
}
}
private bool Validate()
{
var validator = new ValidationHelper();
validator.AddRequiredRule(() => Email, "Email is required.");
validator.AddRequiredRule(() => Password, "Password is required.");
var result = validator.ValidateAll();
Errors = result.AsObservableDictionary();
return result.IsValid;
}
Run Code Online (Sandbox Code Playgroud)
它的好处在于您可以将Errors作为集合获取并在视图中绑定它们.对于Android,我将Error属性设置为键控错误消息.
<EditText
android:minHeight="40dp"
android:layout_margin="4dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:inputType="textEmailAddress"
android:hint="Email"
local:MvxBind="Text Email; Error Errors['Email']"
android:id="@+id/EmailEditText" />
<EditText
android:minHeight="40dp"
android:layout_margin="4dp"
android:inputType="textPassword"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="Password"
local:MvxBind="Text Password; Error Errors['Password']"
android:id="@+id/PasswordEditText" />
Run Code Online (Sandbox Code Playgroud)
这是验证的样子:

编辑:显示帮助程序代码
public static class ValidationResultExtension
{
public static ObservableDictionary<string, string> AsObservableDictionary(this ValidationResult result)
{
var dictionary = new ObservableDictionary<string, string>();
foreach (var item in result.ErrorList)
{
var key = item.Target.ToString();
var text = item.ErrorText;
if (dictionary.ContainsKey(key))
{
dictionary[key] = dictionary.Keys + Environment.NewLine + text;
}
else
{
dictionary[key] = text;
}
}
return dictionary;
}
}
public class ObservableDictionary<TKey, TValue> : IDictionary<TKey, TValue>, INotifyCollectionChanged, INotifyPropertyChanged
{
private const string CountString = "Count";
private const string IndexerName = "Item[]";
private const string KeysName = "Keys";
private const string ValuesName = "Values";
private IDictionary<TKey, TValue> _dictionary;
protected IDictionary<TKey, TValue> Dictionary
{
get { return _dictionary; }
}
public ObservableDictionary()
{
_dictionary = new Dictionary<TKey, TValue>();
}
public ObservableDictionary(IDictionary<TKey, TValue> dictionary)
{
_dictionary = new Dictionary<TKey, TValue>(dictionary);
}
public ObservableDictionary(IEqualityComparer<TKey> comparer)
{
_dictionary = new Dictionary<TKey, TValue>(comparer);
}
public ObservableDictionary(int capacity)
{
_dictionary = new Dictionary<TKey, TValue>(capacity);
}
public ObservableDictionary(IDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey> comparer)
{
_dictionary = new Dictionary<TKey, TValue>(dictionary, comparer);
}
public ObservableDictionary(int capacity, IEqualityComparer<TKey> comparer)
{
_dictionary = new Dictionary<TKey, TValue>(capacity, comparer);
}
#region IDictionary<TKey,TValue> Members
public void Add(TKey key, TValue value)
{
Insert(key, value, true);
}
public bool ContainsKey(TKey key)
{
return Dictionary.ContainsKey(key);
}
public ICollection<TKey> Keys
{
get { return Dictionary.Keys; }
}
public bool Remove(TKey key)
{
if (key == null)
{
throw new ArgumentNullException("key");
}
TValue value;
Dictionary.TryGetValue(key, out value);
var removed = Dictionary.Remove(key);
if (removed)
{
OnCollectionChanged(NotifyCollectionChangedAction.Remove, new KeyValuePair<TKey, TValue>(key, value));
}
return removed;
}
public bool TryGetValue(TKey key, out TValue value)
{
return Dictionary.TryGetValue(key, out value);
}
public ICollection<TValue> Values
{
get { return Dictionary.Values; }
}
public TValue this[TKey key]
{
get
{
return Dictionary.ContainsKey(key) ? Dictionary[key] : default(TValue);
}
set
{
Insert(key, value, false);
}
}
#endregion IDictionary<TKey,TValue> Members
public void Add(KeyValuePair<TKey, TValue> item)
{
Insert(item.Key, item.Value, true);
}
public void Clear()
{
if (Dictionary.Count > 0)
{
Dictionary.Clear();
OnCollectionChanged();
}
}
public bool Contains(KeyValuePair<TKey, TValue> item)
{
return Dictionary.Contains(item);
}
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
Dictionary.CopyTo(array, arrayIndex);
}
public int Count
{
get { return Dictionary.Count; }
}
public bool IsReadOnly
{
get { return Dictionary.IsReadOnly; }
}
public bool Remove(KeyValuePair<TKey, TValue> item)
{
return Remove(item.Key);
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return Dictionary.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)Dictionary).GetEnumerator();
}
public event NotifyCollectionChangedEventHandler CollectionChanged;
public event PropertyChangedEventHandler PropertyChanged;
public void AddRange(IDictionary<TKey, TValue> items)
{
if (items == null)
{
throw new ArgumentNullException("items");
}
if (items.Count > 0)
{
if (Dictionary.Count > 0)
{
if (items.Keys.Any((k) => Dictionary.ContainsKey(k)))
{
throw new ArgumentException("An item with the same key has already been added.");
}
else
{
foreach (var item in items)
{
Dictionary.Add(item);
}
}
}
else
{
_dictionary = new Dictionary<TKey, TValue>(items);
}
OnCollectionChanged(NotifyCollectionChangedAction.Add, items.ToArray());
}
}
private void Insert(TKey key, TValue value, bool add)
{
if (key == null)
{
throw new ArgumentNullException("key");
}
TValue item;
if (Dictionary.TryGetValue(key, out item))
{
if (add)
{
throw new ArgumentException("An item with the same key has already been added.");
}
if (Equals(item, value))
{
return;
}
Dictionary[key] = value;
OnCollectionChanged(NotifyCollectionChangedAction.Replace, new KeyValuePair<TKey, TValue>(key, value), new KeyValuePair<TKey, TValue>(key, item));
}
else
{
Dictionary[key] = value;
OnCollectionChanged(NotifyCollectionChangedAction.Add, new KeyValuePair<TKey, TValue>(key, value));
}
}
private void OnPropertyChanged()
{
OnPropertyChanged(CountString);
OnPropertyChanged(IndexerName);
OnPropertyChanged(KeysName);
OnPropertyChanged(ValuesName);
}
protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
private void OnCollectionChanged()
{
OnPropertyChanged();
if (CollectionChanged != null)
{
CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}
private void OnCollectionChanged(NotifyCollectionChangedAction action, KeyValuePair<TKey, TValue> changedItem)
{
OnPropertyChanged();
if (CollectionChanged != null)
{
CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, changedItem));
}
}
private void OnCollectionChanged(NotifyCollectionChangedAction action, KeyValuePair<TKey, TValue> newItem, KeyValuePair<TKey, TValue> oldItem)
{
OnPropertyChanged();
if (CollectionChanged != null)
{
CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, newItem, oldItem));
}
}
private void OnCollectionChanged(NotifyCollectionChangedAction action, IList newItems)
{
OnPropertyChanged();
if (CollectionChanged != null)
{
CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, newItems));
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4209 次 |
| 最近记录: |