Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- if (bindingGroup.CommitEdit())
- SaveEverything();
- object OnUpdateSourceExceptionFilter(object bindExpression, Exception exception)
- {
- BindingExpression expr = (bindExpression as BindingExpression);
- if (expr.DataItem is IReceivesBindingErrorInformation)
- {
- ((IReceivesBindingErrorInformation)expr.DataItem).ReceiveBindingErrorInformation(expr.ParentBinding.Path.Path, exception);
- }
- // check for FormatException and produce a nicer error
- // ...
- }
- HashSet<string> bindingErrors = new HashSet<string>();
- void IReceivesBindingErrorInformation.ReceiveBindingErrorInformation(string path, Exception exception)
- {
- bindingErrors.Add(path);
- }
- protected ObservableCollection<string> errors = new ObservableCollection<string>();
- public virtual ObservableCollection<string> Errors
- {
- get { return errors; }
- }
- protected ObservableCollection<string> externalErrors = new ObservableCollection<string>();
- public ObservableCollection<string> ExternalErrors
- {
- get { return externalErrors; }
- }
- public virtual bool HasError
- {
- get { return Errors != null && Errors.Count > 0; }
- }
- public override ObservableCollection<string> Errors
- {
- get
- {
- errors = new ObservableCollection<string>();
- errors.AddUniqueIfNotEmpty(this["Name"]);
- errors.AddUniqueIfNotEmpty(this["EmailAddresses"]);
- errors.AddUniqueIfNotEmpty(this["SomeOtherProperty"]);
- errors.AddRange(ExternalErrors);
- return errors;
- }
- }
- public override string this[string propertyName]
- {
- get
- {
- string error = string.Empty;
- if (propertyName == "Name" && Name.IsNullOrEmpty()) error = "You must enter the Name field.";
- else if (propertyName == "EmailAddresses" && EmailAddresses.Count == 0) error = "You must enter at least one e-mail address into the Email address(es) field.";
- else if (propertyName == "SomeOtherProperty" && SomeOtherProperty.IsNullOrEmpty()) error = "You must enter the SomeOtherProperty field.";
- return error;
- }
- }
- private void ValidateUniqueName(Genre genre)
- {
- string errorMessage = "The genre name must be unique";
- if (!IsGenreNameUnique(genre))
- {
- if (!genre.ExternalErrors.Contains(errorMessage)) genre.ExternalErrors.Add(errorMessage);
- }
- else genre.ExternalErrors.Remove(errorMessage);
- }
- private bool IsGenreNameUnique(Genre genre)
- {
- return Genres.Where(d => d.Name != string.Empty && d.Name == genre.Name).Count() == 1;
- }
- public object FooObject { get; set; } // Implement INotifyPropertyChanged
- public int Foo
- {
- get { return FooObject.GetType() == typeof(int) ? int.Parse(FooObject) : -1; }
- }
- public override string this[string propertyName]
- {
- get
- {
- string error = string.Empty;
- if (propertyName == "FooObject" && FooObject.GetType() != typeof(int))
- error = "Please enter a whole number for the Foo field.";
- ...
- return error;
- }
- }
- container.AddHandler(Validation.ErrorEvent, Container_Error);
- ...
- void Container_Error(object sender, ValidationErrorEventArgs e) {
- ...
- }
- public struct Failable<T>
- {
- public T Value { get; private set; }
- public string Text { get; private set; }
- public bool IsValid { get; private set; }
- public Failable(T value)
- {
- Value = value;
- try
- {
- var converter = TypeDescriptor.GetConverter(typeof(T));
- Text = converter.ConvertToString(value);
- IsValid = true;
- }
- catch
- {
- Text = String.Empty;
- IsValid = false;
- }
- }
- public Failable(string text)
- {
- Text = text;
- try
- {
- var converter = TypeDescriptor.GetConverter(typeof(T));
- Value = (T)converter.ConvertFromString(text);
- IsValid = true;
- }
- catch
- {
- Value = default(T);
- IsValid = false;
- }
- }
- }
- public class StringToFailableConverter<T> : IValueConverter
- {
- public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
- {
- if (value.GetType() != typeof(Failable<T>))
- throw new InvalidOperationException("Invalid value type.");
- if (targetType != typeof(string))
- throw new InvalidOperationException("Invalid target type.");
- var rawValue = (Failable<T>)value;
- return rawValue.Text;
- }
- public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
- {
- if (value.GetType() != typeof(string))
- throw new InvalidOperationException("Invalid value type.");
- if (targetType != typeof(Failable<T>))
- throw new InvalidOperationException("Invalid target type.");
- return new Failable<T>(value as string);
- }
- }
- public static class Failable
- {
- public static StringToFailableConverter<Int32> Int32Converter { get; private set; }
- public static StringToFailableConverter<double> DoubleConverter { get; private set; }
- static Failable()
- {
- Int32Converter = new StringToFailableConverter<Int32>();
- DoubleConverter = new StringToFailableConverter<Double>();
- }
- }
- public Failable<int> NumberValue
- {
- //Custom logic along with validation
- //using IsValid property
- }
- <TextBox Text="{Binding NumberValue,Converter={x:Static local:Failable.Int32Converter}}"/>
- public abstract class ViewModelBase : INotifyPropertyChanged
- {
- public event PropertyChangedEventHandler PropertyChanged;
- public void RaisePropertyChanged([CallerMemberName] string propertyName = null)
- {
- if (PropertyChanged != null)
- PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
- }
- }
- public class VmSomeEntity : ViewModelBase, INotifyDataErrorInfo
- {
- //This one is part of INotifyDataErrorInfo interface which I will not use,
- //perhaps in more complicated scenarios it could be used to let some other VM know validation changed.
- public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
- //will hold the errors found in validation.
- public Dictionary<string, string> ValidationErrors = new Dictionary<string, string>();
- //the actual value - notice it is 'int' and not 'string'..
- private int storageCapacityInBytes;
- //this is just to keep things sane - otherwise the view will not be able to send whatever the user throw at it.
- //we want to consume what the user throw at us and validate it - right? :)
- private string storageCapacityInBytesWrapper;
- //This is a property to be served by the View.. important to understand the tactic used inside!
- public string StorageCapacityInBytes
- {
- get { return storageCapacityInBytesWrapper ?? storageCapacityInBytes.ToString(); }
- set
- {
- int result;
- var isValid = int.TryParse(value, out result);
- if (isValid)
- {
- storageCapacityInBytes = result;
- storageCapacityInBytesWrapper = null;
- RaisePropertyChanged();
- }
- else
- storageCapacityInBytesWrapper = value;
- HandleValidationError(isValid, "StorageCapacityInBytes", "Not a number.");
- }
- }
- //Manager for the dictionary
- private void HandleValidationError(bool isValid, string propertyName, string validationErrorDescription)
- {
- if (!string.IsNullOrEmpty(propertyName))
- {
- if (isValid)
- {
- if (ValidationErrors.ContainsKey(propertyName))
- ValidationErrors.Remove(propertyName);
- }
- else
- {
- if (!ValidationErrors.ContainsKey(propertyName))
- ValidationErrors.Add(propertyName, validationErrorDescription);
- else
- ValidationErrors[propertyName] = validationErrorDescription;
- }
- }
- }
- // this is another part of the interface - will be called automatically
- public IEnumerable GetErrors(string propertyName)
- {
- return ValidationErrors.ContainsKey(propertyName)
- ? ValidationErrors[propertyName]
- : null;
- }
- // same here, another part of the interface - will be called automatically
- public bool HasErrors
- {
- get
- {
- return ValidationErrors.Count > 0;
- }
- }
- }
Add Comment
Please, Sign In to add comment