Mercurial > silverbladetech
diff Chronosv2/source/Presentation/ViewModel/WindowViewModel.cs @ 10:443821e55f06
Initial cleaned up add from Codeplex files
author | stevenh7776 stevenhollidge@hotmail.com |
---|---|
date | Tue, 21 Feb 2012 17:25:44 +0700 |
parents | |
children | 09d18d6e5f40 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Chronosv2/source/Presentation/ViewModel/WindowViewModel.cs Tue Feb 21 17:25:44 2012 +0700 @@ -0,0 +1,466 @@ +/* +The MIT License + +Copyright (c) 2009-2010. Carlos Guzmán Álvarez. http://chronoswpf.codeplex.com/ + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +using System; +using System.ComponentModel; +using System.Threading; +using System.Threading.Tasks; +using Chronos.Presentation.Core.ViewModel; +using Chronos.Presentation.Core.Windows; +using NLog; +using nRoute.Components; + +namespace Chronos.Presentation.ViewModel +{ + public abstract class WindowViewModel<TEntity> + : NavigationViewModel, IWindowViewModel where TEntity: class, new() + { + #region · Logger · + + private static Logger Logger = LogManager.GetCurrentClassLogger(); + + #endregion + + #region · Inner Types · + + [Serializable] + protected enum InquiryActionResultType + { + DataFetched, + RequestedNew, + DataNotFound + } + + protected sealed class InquiryActionResult<TResult> + where TResult : class + { + #region · Properties · + + public TResult Data + { + get; + set; + } + + public InquiryActionResultType Result + { + get; + set; + } + + #endregion + + #region · Constructors · + + public InquiryActionResult() + { + } + + #endregion + } + + #endregion + + #region · PropertyChangedEventArgs Cached Instances · + + private static readonly PropertyChangedEventArgs ViewModeChangedArgs = CreateArgs<WindowViewModel<TEntity>>(x => x.ViewMode); + private static readonly PropertyChangedEventArgs StatusMessageChangedArgs = CreateArgs<WindowViewModel<TEntity>>(x => x.StatusMessage); + private static readonly PropertyChangedEventArgs NotificationMessageChangedArgs = CreateArgs<WindowViewModel<TEntity>>(x => x.NotificationMessage); + + #endregion + + #region · Events · + + /// <summary> + /// Occurs when view mode is changed. + /// </summary> + public event EventHandler ViewModeChanged; + + #endregion + + #region · Fields · + + private TEntity originalEntity; + private string statusMessage; + private string notificationMessage; + private TEntity entity; + private ViewModeType viewMode; + private PropertyStateCollection<TEntity> propertyStates; + + #region · Commands · + + private ActionCommand inquiryCommand; + + #endregion + + #endregion + + #region · Properties · + + /// <summary> + /// Gets the property state collection + /// </summary> + public PropertyStateCollection<TEntity> PropertyStates + { + get + { + if (this.propertyStates == null) + { + this.propertyStates = new PropertyStateCollection<TEntity>(); + } + + return this.propertyStates; + } + } + + /// <summary> + /// Gets or sets the state of the smart part. + /// </summary> + /// <value>The state of the smart part.</value> + public ViewModeType ViewMode + { + get { return this.viewMode; } + set + { + if (this.viewMode != value) + { + this.viewMode = value; + try + { + this.OnViewModeChanged(); + } + catch + { +#warning TODO: This is done to prevent DataGrid erroros when discarding changes on new records + } + } + } + } + + /// <summary> + /// Gets the inquiry data command + /// </summary> + public ActionCommand InquiryCommand + { + get + { + if (this.inquiryCommand == null) + { + this.inquiryCommand = new ActionCommand + ( + () => OnInquiryData(), + () => CanInquiryData() + ); + } + + return this.inquiryCommand; + } + } + + /// <summary> + /// Gets or sets the status message text + /// </summary> + public string StatusMessage + { + get { return this.statusMessage; } + set + { + if (this.statusMessage != value) + { + this.statusMessage = value; + this.NotifyPropertyChanged(StatusMessageChangedArgs); + } + } + } + + /// <summary> + /// Gets or sets the notification message text + /// </summary> + public string NotificationMessage + { + get { return this.notificationMessage; } + set + { + if (this.notificationMessage != value) + { + this.notificationMessage = value; + this.NotifyPropertyChanged(NotificationMessageChangedArgs); + } + } + } + + #endregion + + #region · Protected Properties · + + /// <summary> + /// Gets or sets the data model. + /// </summary> + /// <value>The data model.</value> + protected TEntity Entity + { + get { return this.entity; } + private set + { + if (!Object.ReferenceEquals(this.entity, value)) + { + this.entity = value; + } + } + } + + protected TEntity OriginalEntity + { + get { return this.originalEntity; } + set { this.originalEntity = value; } + } + + #endregion + + #region · Constructors · + + protected WindowViewModel() + : base() + { + this.InitializePropertyStates(); + + this.Entity = new TEntity(); + this.ViewMode = ViewModeType.ViewOnly; + } + + #endregion + + #region · Command Actions · + + #region · Inquiry · + + protected virtual bool CanInquiryData() + { + return (this.ViewMode == ViewModeType.ViewOnly); + } + + protected void OnInquiryData() + { + InquiryActionResult<TEntity> result = new InquiryActionResult<TEntity> + { + Result = InquiryActionResultType.DataNotFound + }; + + this.ViewMode = ViewModeType.Busy; + this.StatusMessage = "Obteniendo datos, espere por favor ..."; + + Task task = Task.Factory.StartNew + ( + (o) => + { + Logger.Debug("Obteniendo datos '{0}'", this.Entity.ToString()); + + this.OnInquiryAction(result); + }, result + ); + + task.ContinueWith + ( + (t) => + { + Logger.Debug("Error al obtener datos '{0}'", t.Exception.InnerException.ToString()); + + this.OnInquiryActionFailed(); + + Exception exception = null; + this.OriginalEntity = null; + + if (t.Exception.InnerException != null) + { + exception = t.Exception.InnerException; + } + else + { + exception = t.Exception; + } + + this.NotificationMessage = exception.Message; + }, + CancellationToken.None, + TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.AttachedToParent, + TaskScheduler.FromCurrentSynchronizationContext() + ); + + task.ContinueWith + ( + _ => + { + Logger.Debug("Datos obtenidos correctamente '{0}'", this.Entity.ToString()); + + this.StatusMessage = null; + this.OnInquiryActionComplete(result); + }, + CancellationToken.None, + TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.AttachedToParent, + TaskScheduler.FromCurrentSynchronizationContext() + ); + } + + protected abstract void OnInquiryAction(InquiryActionResult<TEntity> result); + + protected virtual void OnInquiryActionComplete(InquiryActionResult<TEntity> result) + { + switch (result.Result) + { + case InquiryActionResultType.DataNotFound: + this.OriginalEntity = null; + + this.ResetDataModel(); + + this.ViewMode = ViewModeType.ViewOnly; + break; + + case InquiryActionResultType.RequestedNew: + throw new InvalidOperationException("Requested New is not valid on this type of ViewModel"); + + case InquiryActionResultType.DataFetched: + this.ResetDataModel(result.Data); + + this.OriginalEntity = this.entity; + this.ViewMode = ViewModeType.ViewOnly; + break; + } + } + + protected virtual void OnInquiryActionFailed() + { + this.ViewMode = ViewModeType.ViewOnly; + } + + #endregion + + #endregion + + #region · Overriden Methods · + + /// <summary> + /// Called when the related view is being closed. + /// </summary> + public override void Close() + { + Logger.Debug("Cerrar ventana '{0}'", this.GetType()); + + if (this.originalEntity != null) + { + this.originalEntity = null; + } + if (this.entity != null) + { + this.entity = null; + } + if (this.propertyStates != null) + { + this.propertyStates.Clear(); + this.propertyStates = null; + } + + this.inquiryCommand = null; + this.statusMessage = null; + this.notificationMessage = null; + + base.Close(); + } + + #endregion + + #region · DataModel Reset Methods · + + protected void ResetDataModel() + { + Logger.Debug("Resetar model '{0}'", this.GetType()); + this.ResetDataModel(new TEntity()); + Logger.Debug("Model reseteado '{0}'", this.GetType()); + } + + protected virtual void ResetDataModel(TEntity model) + { + this.OnResetingDataModel(this.Entity, model); + + this.OriginalEntity = null; + this.Entity = model; + + this.OnResetedDataModel(model); + } + + protected virtual void OnResetingDataModel(TEntity oldModel, TEntity newModel) + { + } + + protected virtual void OnResetedDataModel(TEntity newModel) + { + this.NotifyAllPropertiesChanged(); + } + + #endregion + + #region · Protected Methods · + + protected virtual void InitializePropertyStates() + { + } + + protected virtual void OnViewModeChanged() + { + if (this.ViewModeChanged != null) + { + this.ViewModeChanged(this, new EventArgs()); + } + + this.NotifyPropertyChanged(ViewModeChangedArgs); + } + + protected virtual void UpdateAllowedUserActions() + { + this.Invoke + ( + () => + { + this.InquiryCommand.RequeryCanExecute(); + } + ); + } + + protected override void NotifyPropertyChanged(PropertyChangedEventArgs args) + { + if (args != StatusMessageChangedArgs) + { + this.StatusMessage = null; + } + if (args != NotificationMessageChangedArgs) + { + this.NotificationMessage = null; + } + + this.UpdateAllowedUserActions(); + base.NotifyPropertyChanged(args); + } + + #endregion + } +}