public interface IViewModel
{
void RaisePropertyChangedEvent(string property);
}
public enum NotificationSeverityEnum
{
INFORMATION,
WARNING,
ERROR,
NONE
}
public interface INotificationMessage
{
string Message { get; set; }
NotificationSeverityEnum Severity { get; set; }
bool IsValid { get; set; }
}
public class ActionResultCollection : ObservableCollection<INotificationMessage>
{
#region Helpers
protected override void InsertItem(int index, INotificationMessage item)
{
if (item != null)
{
base.InsertItem(index, item);
}
}
public bool HasValidationErrors
{
get
{
return this.Any(i => i.Severity == NotificationSeverityEnum.ERROR);
}
}
public bool HasValidationWarnings
{
get
{
return this.Any(i => i.Severity == NotificationSeverityEnum.WARNING);
}
}
public bool HasValidationInformations
{
get
{
return this.Any(i => i.Severity == NotificationSeverityEnum.INFORMATION);
}
}
public bool PassAllValidations
{
get { return !this.Any(); }
}
public NotificationSeverityEnum GetHighestSeverityResult
{
get
{
if (this.Items.Any(i => i != null && i.Severity == NotificationSeverityEnum.ERROR))
{
return NotificationSeverityEnum.ERROR;
}
if (this.Items.Any(i => i.Severity == NotificationSeverityEnum.WARNING))
{
return NotificationSeverityEnum.WARNING;
}
if (this.Items.Any(i => i.Severity == NotificationSeverityEnum.INFORMATION))
{
return NotificationSeverityEnum.INFORMATION;
}
return NotificationSeverityEnum.NONE;
}
}
public void AddRange(IEnumerable<INotificationMessage> collection)
{
if (collection == null)
{
return;
}
foreach (INotificationMessage msg in collection)
{
this.Add(msg);
}
}
public string Severity
{
get
{
if (this.Items.Any(i => i != null && i.Severity == NotificationSeverityEnum.ERROR))
{
return NotificationConstants.Severity.ERROR;
}
if (this.Items.Any(i => i.Severity == NotificationSeverityEnum.WARNING))
{
return NotificationConstants.Severity.WARNING;
}
if (this.Items.Any(i => i.Severity == NotificationSeverityEnum.INFORMATION))
{
return NotificationConstants.Severity.INFORMATION;
}
return NotificationConstants.Severity.INFORMATION;
}
}
#endregion
#region Constructors
public ActionResultCollection() { }
public ActionResultCollection(INotificationMessage notificationMessage)
{
if (notificationMessage != null)
Add(notificationMessage);
}
public ActionResultCollection(IEnumerable<INotificationMessage> messages)
{
AddRange(messages.Where(m => m != null));
}
#endregion Constructors
#region Factory
public static ActionResultCollection Create(INotificationMessage notificationMessage)
{
return new ActionResultCollection(notificationMessage);
}
public static ActionResultCollection Create(IEnumerable<INotificationMessage> messages)
{
return new ActionResultCollection(messages);
}
public static ActionResultCollection Create(IEnumerable<string> validationErrors)
{
if (validationErrors == null ||
!validationErrors.Any())
{
return null;
}
ActionResultCollection results = new ActionResultCollection();
foreach (string validationError in validationErrors)
{
results.Add(new ValidationActionResult(false, validationError, NotificationSeverityEnum.ERROR));
}
return results;
}
public static ActionResultCollection Create(string validationError)
{
return string.IsNullOrWhiteSpace(validationError)
? new ActionResultCollection()
: new ActionResultCollection() { new ValidationActionResult(false, validationError, NotificationSeverityEnum.ERROR) };
}
public static ActionResultCollection CreateErrorResults(IEnumerable<string> errorMessages)
{
if (errorMessages == null)
return null;
return new ActionResultCollection(errorMessages.Where(m => !string.IsNullOrWhiteSpace(m)).Select(m => new ErrorActionResult(m)));
}
#endregion Factory
}
ViewModelBase.cs
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using log4net;
namespace EvanTest.ViewModels
{
public abstract class ViewModelBase : INotifyPropertyChanged, IViewModel
{
public static readonly ILog Log = LogManager.GetLogger(typeof(ViewModelBase));
#region Shared Memebers
private ILog _logInstance;
public ILog LogInstance
{
get
{
if (_logInstance == null)
{
_logInstance = this.GetViewModelLogInstance();
}
return _logInstance;
}
}
public bool IsFirstInitialize { get; set; }
#endregion
#region Constructors
protected ViewModelBase()
{
this.ValidationResults = new ActionResultCollection();
this.ValidationResultsForWarning = new ActionResultCollection();
}
#endregion
#region INotifyPropertyChanged Convenience Methods
protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (Equals(storage, value))
{
return false;
}
storage = value;
this.OnPropertyChanged(propertyName);
return true;
}
protected bool SetProperty<T>(ref T storage, T value, out T oldValue, [CallerMemberName] string propertyName = null)
{
oldValue = storage;
return SetProperty(ref storage, value, propertyName);
}
#endregion INotifyPropertyChanged Convenience Methods
#region INotifyPropertyChanged
public event PropertyChangedEventHandler ValidationResultsChanged;
public event PropertyChangedEventHandler PropertyChanged;
public event PropertyChangedEventHandler ThrowPropChange;
/// <summary>
/// Raises this object's PropertyChanged Event
/// </summary>
/// <param name="property"></param>
public void RaisePropertyChangedEvent(string property)
{
this.OnPropertyChanged(property);
}
/// <summary>
/// Raises this object's PropertyChanged event.
/// </summary>
/// <param name="property">The property that has a new value.</param>
protected virtual void OnPropertyChanged(string property)
{
try
{
var handler = this.PropertyChanged;
if (handler == null)
{
return;
}
var e = new PropertyChangedEventArgs(property);
handler(this, e);
}
catch (Exception ex)
{
Log.Error($"OnPropertyChanged got error on {property}.", ex);
return;
}
}
/// <summary>
/// Warns the developer if this object does not have
/// a public property with the specified name. This
/// method does not exist in a Release build.
/// </summary>
//[Conditional("DEBUG")]
//[DebuggerStepThrough]
public bool VerifyPropertyName(string property)
{
// Verify that the property name matches a real,
// public, instance property on this object.
if (TypeDescriptor.GetProperties(this)[property] == null)
{
return false;
//var msg = "Invalid property name: " + propertyName;
//if (this.ThrowOnInvalidPropertyName)
// throw new Exception(msg);
//Debug.Fail(msg);
}
return true;
}
/// <summary>
/// Returns whether an exception is thrown, or if a Debug.Fail() is used
/// when an invalid property name is passed to the VerifyPropertyName method.
/// The default value is false, but subclasses used by unit tests might
/// override this property's getter to return true.
/// </summary>
protected virtual bool ThrowOnInvalidPropertyName { get; private set; }
#endregion
#region Validation
private ActionResultCollection _validationResults;
public ActionResultCollection ValidationResults
{
get { return _validationResults; }
set
{
_validationResults = value;
OnPropertyChanged(nameof(ValidationResults));
ValidationResultsChanged?.Invoke(this, null);
}
}
private ActionResultCollection _validationResultsForWarning;
public ActionResultCollection ValidationResultsForWarning
{
get { return _validationResultsForWarning; }
set
{
_validationResultsForWarning = value;
OnPropertyChanged(nameof(ValidationResultsForWarning));
ValidationResultsChanged?.Invoke(this, null);
}
}
public virtual void ClearValidationResults()
{
this.ValidationResults = new ActionResultCollection();
this.ValidationResultsForWarning = new ActionResultCollection();
}
#endregion
#region Window Helpers
private string _windowTitle;
public string WindowTitle
{
get { return _windowTitle; }
set
{
_windowTitle = value;
OnPropertyChanged("WindowTitle");
}
}
#endregion
#region Custom Child Update Implementation
public void RaiseThrowPropChange(object sender, PropertyChangedEventArgs e)
{
if (ThrowPropChange != null)
{
ThrowPropChange(sender, e);
}
}
public void CatchThrowPropChange(object sender, PropertyChangedEventArgs e)
{
OnPropertyChanged(e.PropertyName);
}
#endregion
#region Event
public EventHandler<MessageBoxShowEventArgs> MessageBoxShow;
/// <summary>
/// [Obsolete, please use ConfirmDecisionInstance.Notify instead.]
/// </summary>
/// <param name="windowTitle"></param>
/// <param name="message"></param>
/// <param name="buttonContext"></param>
public void MessageBoxShowEvent(string windowTitle, string message, string buttonContext)
{
MessageBoxShow(this, new MessageBoxShowEventArgs(windowTitle, message, buttonContext));
}
#endregion
#region Help methods
public ILog GetViewModelLogInstance()
{
return LogManager.GetLogger(this.GetType());
}
#endregion
}
}