comparison 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
comparison
equal deleted inserted replaced
9:904a9faadf8b 10:443821e55f06
1 /*
2 The MIT License
3
4 Copyright (c) 2009-2010. Carlos Guzmán Álvarez. http://chronoswpf.codeplex.com/
5
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 THE SOFTWARE.
23 */
24
25 using System;
26 using System.ComponentModel;
27 using System.Threading;
28 using System.Threading.Tasks;
29 using Chronos.Presentation.Core.ViewModel;
30 using Chronos.Presentation.Core.Windows;
31 using NLog;
32 using nRoute.Components;
33
34 namespace Chronos.Presentation.ViewModel
35 {
36 public abstract class WindowViewModel<TEntity>
37 : NavigationViewModel, IWindowViewModel where TEntity: class, new()
38 {
39 #region · Logger ·
40
41 private static Logger Logger = LogManager.GetCurrentClassLogger();
42
43 #endregion
44
45 #region · Inner Types ·
46
47 [Serializable]
48 protected enum InquiryActionResultType
49 {
50 DataFetched,
51 RequestedNew,
52 DataNotFound
53 }
54
55 protected sealed class InquiryActionResult<TResult>
56 where TResult : class
57 {
58 #region · Properties ·
59
60 public TResult Data
61 {
62 get;
63 set;
64 }
65
66 public InquiryActionResultType Result
67 {
68 get;
69 set;
70 }
71
72 #endregion
73
74 #region · Constructors ·
75
76 public InquiryActionResult()
77 {
78 }
79
80 #endregion
81 }
82
83 #endregion
84
85 #region · PropertyChangedEventArgs Cached Instances ·
86
87 private static readonly PropertyChangedEventArgs ViewModeChangedArgs = CreateArgs<WindowViewModel<TEntity>>(x => x.ViewMode);
88 private static readonly PropertyChangedEventArgs StatusMessageChangedArgs = CreateArgs<WindowViewModel<TEntity>>(x => x.StatusMessage);
89 private static readonly PropertyChangedEventArgs NotificationMessageChangedArgs = CreateArgs<WindowViewModel<TEntity>>(x => x.NotificationMessage);
90
91 #endregion
92
93 #region · Events ·
94
95 /// <summary>
96 /// Occurs when view mode is changed.
97 /// </summary>
98 public event EventHandler ViewModeChanged;
99
100 #endregion
101
102 #region · Fields ·
103
104 private TEntity originalEntity;
105 private string statusMessage;
106 private string notificationMessage;
107 private TEntity entity;
108 private ViewModeType viewMode;
109 private PropertyStateCollection<TEntity> propertyStates;
110
111 #region · Commands ·
112
113 private ActionCommand inquiryCommand;
114
115 #endregion
116
117 #endregion
118
119 #region · Properties ·
120
121 /// <summary>
122 /// Gets the property state collection
123 /// </summary>
124 public PropertyStateCollection<TEntity> PropertyStates
125 {
126 get
127 {
128 if (this.propertyStates == null)
129 {
130 this.propertyStates = new PropertyStateCollection<TEntity>();
131 }
132
133 return this.propertyStates;
134 }
135 }
136
137 /// <summary>
138 /// Gets or sets the state of the smart part.
139 /// </summary>
140 /// <value>The state of the smart part.</value>
141 public ViewModeType ViewMode
142 {
143 get { return this.viewMode; }
144 set
145 {
146 if (this.viewMode != value)
147 {
148 this.viewMode = value;
149 try
150 {
151 this.OnViewModeChanged();
152 }
153 catch
154 {
155 #warning TODO: This is done to prevent DataGrid erroros when discarding changes on new records
156 }
157 }
158 }
159 }
160
161 /// <summary>
162 /// Gets the inquiry data command
163 /// </summary>
164 public ActionCommand InquiryCommand
165 {
166 get
167 {
168 if (this.inquiryCommand == null)
169 {
170 this.inquiryCommand = new ActionCommand
171 (
172 () => OnInquiryData(),
173 () => CanInquiryData()
174 );
175 }
176
177 return this.inquiryCommand;
178 }
179 }
180
181 /// <summary>
182 /// Gets or sets the status message text
183 /// </summary>
184 public string StatusMessage
185 {
186 get { return this.statusMessage; }
187 set
188 {
189 if (this.statusMessage != value)
190 {
191 this.statusMessage = value;
192 this.NotifyPropertyChanged(StatusMessageChangedArgs);
193 }
194 }
195 }
196
197 /// <summary>
198 /// Gets or sets the notification message text
199 /// </summary>
200 public string NotificationMessage
201 {
202 get { return this.notificationMessage; }
203 set
204 {
205 if (this.notificationMessage != value)
206 {
207 this.notificationMessage = value;
208 this.NotifyPropertyChanged(NotificationMessageChangedArgs);
209 }
210 }
211 }
212
213 #endregion
214
215 #region · Protected Properties ·
216
217 /// <summary>
218 /// Gets or sets the data model.
219 /// </summary>
220 /// <value>The data model.</value>
221 protected TEntity Entity
222 {
223 get { return this.entity; }
224 private set
225 {
226 if (!Object.ReferenceEquals(this.entity, value))
227 {
228 this.entity = value;
229 }
230 }
231 }
232
233 protected TEntity OriginalEntity
234 {
235 get { return this.originalEntity; }
236 set { this.originalEntity = value; }
237 }
238
239 #endregion
240
241 #region · Constructors ·
242
243 protected WindowViewModel()
244 : base()
245 {
246 this.InitializePropertyStates();
247
248 this.Entity = new TEntity();
249 this.ViewMode = ViewModeType.ViewOnly;
250 }
251
252 #endregion
253
254 #region · Command Actions ·
255
256 #region · Inquiry ·
257
258 protected virtual bool CanInquiryData()
259 {
260 return (this.ViewMode == ViewModeType.ViewOnly);
261 }
262
263 protected void OnInquiryData()
264 {
265 InquiryActionResult<TEntity> result = new InquiryActionResult<TEntity>
266 {
267 Result = InquiryActionResultType.DataNotFound
268 };
269
270 this.ViewMode = ViewModeType.Busy;
271 this.StatusMessage = "Obteniendo datos, espere por favor ...";
272
273 Task task = Task.Factory.StartNew
274 (
275 (o) =>
276 {
277 Logger.Debug("Obteniendo datos '{0}'", this.Entity.ToString());
278
279 this.OnInquiryAction(result);
280 }, result
281 );
282
283 task.ContinueWith
284 (
285 (t) =>
286 {
287 Logger.Debug("Error al obtener datos '{0}'", t.Exception.InnerException.ToString());
288
289 this.OnInquiryActionFailed();
290
291 Exception exception = null;
292 this.OriginalEntity = null;
293
294 if (t.Exception.InnerException != null)
295 {
296 exception = t.Exception.InnerException;
297 }
298 else
299 {
300 exception = t.Exception;
301 }
302
303 this.NotificationMessage = exception.Message;
304 },
305 CancellationToken.None,
306 TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.AttachedToParent,
307 TaskScheduler.FromCurrentSynchronizationContext()
308 );
309
310 task.ContinueWith
311 (
312 _ =>
313 {
314 Logger.Debug("Datos obtenidos correctamente '{0}'", this.Entity.ToString());
315
316 this.StatusMessage = null;
317 this.OnInquiryActionComplete(result);
318 },
319 CancellationToken.None,
320 TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.AttachedToParent,
321 TaskScheduler.FromCurrentSynchronizationContext()
322 );
323 }
324
325 protected abstract void OnInquiryAction(InquiryActionResult<TEntity> result);
326
327 protected virtual void OnInquiryActionComplete(InquiryActionResult<TEntity> result)
328 {
329 switch (result.Result)
330 {
331 case InquiryActionResultType.DataNotFound:
332 this.OriginalEntity = null;
333
334 this.ResetDataModel();
335
336 this.ViewMode = ViewModeType.ViewOnly;
337 break;
338
339 case InquiryActionResultType.RequestedNew:
340 throw new InvalidOperationException("Requested New is not valid on this type of ViewModel");
341
342 case InquiryActionResultType.DataFetched:
343 this.ResetDataModel(result.Data);
344
345 this.OriginalEntity = this.entity;
346 this.ViewMode = ViewModeType.ViewOnly;
347 break;
348 }
349 }
350
351 protected virtual void OnInquiryActionFailed()
352 {
353 this.ViewMode = ViewModeType.ViewOnly;
354 }
355
356 #endregion
357
358 #endregion
359
360 #region · Overriden Methods ·
361
362 /// <summary>
363 /// Called when the related view is being closed.
364 /// </summary>
365 public override void Close()
366 {
367 Logger.Debug("Cerrar ventana '{0}'", this.GetType());
368
369 if (this.originalEntity != null)
370 {
371 this.originalEntity = null;
372 }
373 if (this.entity != null)
374 {
375 this.entity = null;
376 }
377 if (this.propertyStates != null)
378 {
379 this.propertyStates.Clear();
380 this.propertyStates = null;
381 }
382
383 this.inquiryCommand = null;
384 this.statusMessage = null;
385 this.notificationMessage = null;
386
387 base.Close();
388 }
389
390 #endregion
391
392 #region · DataModel Reset Methods ·
393
394 protected void ResetDataModel()
395 {
396 Logger.Debug("Resetar model '{0}'", this.GetType());
397 this.ResetDataModel(new TEntity());
398 Logger.Debug("Model reseteado '{0}'", this.GetType());
399 }
400
401 protected virtual void ResetDataModel(TEntity model)
402 {
403 this.OnResetingDataModel(this.Entity, model);
404
405 this.OriginalEntity = null;
406 this.Entity = model;
407
408 this.OnResetedDataModel(model);
409 }
410
411 protected virtual void OnResetingDataModel(TEntity oldModel, TEntity newModel)
412 {
413 }
414
415 protected virtual void OnResetedDataModel(TEntity newModel)
416 {
417 this.NotifyAllPropertiesChanged();
418 }
419
420 #endregion
421
422 #region · Protected Methods ·
423
424 protected virtual void InitializePropertyStates()
425 {
426 }
427
428 protected virtual void OnViewModeChanged()
429 {
430 if (this.ViewModeChanged != null)
431 {
432 this.ViewModeChanged(this, new EventArgs());
433 }
434
435 this.NotifyPropertyChanged(ViewModeChangedArgs);
436 }
437
438 protected virtual void UpdateAllowedUserActions()
439 {
440 this.Invoke
441 (
442 () =>
443 {
444 this.InquiryCommand.RequeryCanExecute();
445 }
446 );
447 }
448
449 protected override void NotifyPropertyChanged(PropertyChangedEventArgs args)
450 {
451 if (args != StatusMessageChangedArgs)
452 {
453 this.StatusMessage = null;
454 }
455 if (args != NotificationMessageChangedArgs)
456 {
457 this.NotificationMessage = null;
458 }
459
460 this.UpdateAllowedUserActions();
461 base.NotifyPropertyChanged(args);
462 }
463
464 #endregion
465 }
466 }