using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Reflection; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Controls; using Tango.Core; using Tango.Core.DI; namespace Tango.SharedUI { /// /// Represents an abstract view model. /// /// /// public abstract class ViewModel : ExtendedObject, INotifyDataErrorInfo { private List> _currentErrors = new List>(); //Holds the current validation errors. private bool _hasErrors; /// /// Gets a value that indicates whether the entity has validation errors. /// public bool HasErrors { get { return _hasErrors; } set { _hasErrors = value; RaisePropertyChangedAuto(); } } private bool _isBusy; /// /// Gets or sets a value indicating whether this view model is currently busy doing operations. /// public bool IsBusy { get { return _isBusy; } set { _isBusy = value; RaisePropertyChangedAuto(); RaisePropertyChanged(nameof(IsFree)); InvalidateRelayCommands(); } } /// /// Gets or sets a value indicating whether this view model is free to perform actions. /// public bool IsFree { get { return !IsBusy; } set { IsBusy = !value; } } private ObservableCollection _validationErrors; /// /// Gets or sets the validation errors. /// public ObservableCollection ValidationErrors { get { return _validationErrors; } protected set { _validationErrors = value; RaisePropertyChangedAuto(); } } /// /// Occurs when the validation errors have changed for a property or for the entire entity. /// public event EventHandler ErrorsChanged; /// /// Initializes a new instance of the class. /// public ViewModel() { IsFree = true; } /// /// Gets the validation errors for a specified property or for the entire entity. /// /// The name of the property to retrieve validation errors for; or null or , to retrieve entity-level errors. /// /// The validation errors for the property or entity. /// public virtual IEnumerable GetErrors(string propertyName) { return _currentErrors.Where(x => x.Key == propertyName).Select(x => x.Value).ToList(); } /// /// Invoked the event. /// /// Name of the property. protected void RaiseError(String propName) { ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propName)); } /// /// Validates this view model by validation attributes. /// /// protected bool Validate() { HasErrors = false; _currentErrors.Clear(); if (ValidationErrors == null) { ValidationErrors = new ObservableCollection(); } ValidationErrors.Clear(); OnValidating(); foreach (var prop in this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) { foreach (var validation in prop.GetCustomAttributes()) { if (!validation.IsValid(prop.GetValue(this))) { _currentErrors.Add(new KeyValuePair(prop.Name, validation.ErrorMessage)); ValidationErrors.Add(validation.ErrorMessage); } } HasErrors = _currentErrors.Count > 0; RaiseError(prop.Name); } return !HasErrors; } /// /// Inserts the specified property error (Use inside OnValidating). /// /// Name of the property. /// The error. protected void InsertError(String propName, String error) { _currentErrors.Add(new KeyValuePair(propName, error)); } /// /// Called before validating. /// protected virtual void OnValidating() { } /// /// Posts the specified message using the messenger service. /// /// /// The message. /// protected virtual T PostMessage(T message) { TangoMessenger.Default.Send(message); return message; } /// /// Registers a messenger message handler. /// /// /// The handler. protected virtual void RegisterMessage(Action handler) { TangoMessenger.Default.Register(handler); } } /// /// Represents an abstract view model which expects an of the specified type T. /// /// /// /// public abstract class ViewModel : ViewModel where T : IView { /// /// Gets or sets the view. /// public T View { get; set; } /// /// Initializes a new instance of the class. /// public ViewModel() : base() { TangoIOC.Default.GetInstanceWhenAvailable((view) => { View = view; OnViewAttached(); }); } /// /// Called when the is loaded and attached. /// protected virtual void OnViewAttached() { } } }