9using System.Collections;
10using System.Collections.Specialized;
11using System.ComponentModel;
12using System.ComponentModel.DataAnnotations;
13using System.Threading.Tasks;
34#if ANDROID || IOS || XAMARIN
35 public abstract class ViewModelBase<T> : INotifyPropertyChanged, IViewModel
43#if ANDROID || IOS || XAMARIN || WINDOWS_UWP
50 get {
return _model; }
53 if (!ReferenceEquals(value, _model))
55 var oldValue = _model;
57 this.OnModelChanged((T)oldValue, _model);
58 OnPropertyChanged(nameof(Model));
66 public static readonly DependencyProperty ModelProperty =
68 new PropertyMetadata((o, e) =>
71 viewmodel.OnModelChanged((T)e.OldValue, (T)e.NewValue);
79 get {
return (T)GetValue(ModelProperty); }
80 set { SetValue(ModelProperty, value); }
89#if ANDROID || IOS || XAMARIN
90 public bool ManageObjectLifetimeProperty;
92 public static readonly DependencyProperty ManageObjectLifetimeProperty =
93 DependencyProperty.Register(
"ManageObjectLifetime", typeof(
bool),
102 [Display(AutoGenerateField =
false)]
103 [ScaffoldColumn(
false)]
104 public bool ManageObjectLifetime
106#if ANDROID || IOS || XAMARIN
107 get {
return (
bool)ManageObjectLifetimeProperty; }
108 set { ManageObjectLifetimeProperty = value; }
110 get {
return (
bool)GetValue(ManageObjectLifetimeProperty); }
111 set { SetValue(ManageObjectLifetimeProperty, value); }
115 private bool _isBusy;
123 get {
return _isBusy; }
126 if (value != _isBusy)
129 OnPropertyChanged(nameof(IsBusy));
135 private bool _isDirty;
141 public virtual bool IsDirty
149 if (_isDirty != value)
152 OnPropertyChanged(nameof(IsDirty));
157 private bool _isValid;
163 public virtual bool IsValid
171 if (_isValid != value)
174 OnPropertyChanged(nameof(IsValid));
179 private bool _canSave =
false;
185 public virtual bool CanSave
193 if (_canSave != value)
196 OnPropertyChanged(nameof(CanSave));
201 private bool _canCancel =
false;
207 public virtual bool CanCancel
215 if (_canCancel != value)
218 OnPropertyChanged(nameof(CanCancel));
223 private bool _canCreate =
false;
230 public virtual bool CanCreate
238 if (_canCreate != value)
241 OnPropertyChanged(nameof(CanCreate));
246 private bool _canDelete =
false;
252 public virtual bool CanDelete
260 if (_canDelete != value)
263 OnPropertyChanged(nameof(CanDelete));
268 private bool _canFetch =
false;
275 public virtual bool CanFetch
283 if (_canFetch != value)
286 OnPropertyChanged(nameof(CanFetch));
291 private bool _canRemove =
false;
297 public virtual bool CanRemove
305 if (_canRemove != value)
308 OnPropertyChanged(nameof(CanRemove));
313 private bool _canAddNew =
false;
319 public virtual bool CanAddNew
327 if (_canAddNew != value)
330 OnPropertyChanged(nameof(CanAddNew));
335 private void SetProperties()
337 bool isObjectBusy =
false;
346 IsDirty = targetObject.IsDirty;
347 IsValid = targetObject.IsValid;
348 CanSave = CanEditObject && targetObject.IsSavable && !isObjectBusy;
349 CanCancel = CanEditObject && targetObject.IsDirty && !isObjectBusy;
350 CanCreate = CanCreateObject && !targetObject.IsDirty && !isObjectBusy;
351 CanDelete = CanDeleteObject && !isObjectBusy && canDeleteInstance;
352 CanFetch = CanGetObject && !targetObject.IsDirty && !isObjectBusy;
355 if (Model is ICollection list)
357 Type itemType = Utilities.GetChildItemType(Model.GetType());
358 if (itemType ==
null)
366 list.Count > 0 && !isObjectBusy;
379 else if (Model is ICollection list)
381 Type itemType = Utilities.GetChildItemType(Model.GetType());
382 if (itemType ==
null)
390 list.Count > 0 && !isObjectBusy;
400 CanCreate = CanCreateObject;
402 CanFetch = CanGetObject && !IsBusy;
409 private bool _canCreateObject;
415 public virtual bool CanCreateObject
419 SetPropertiesAtObjectLevel();
420 return _canCreateObject;
424 if (_canCreateObject != value)
426 _canCreateObject = value;
427 OnPropertyChanged(nameof(CanCreateObject));
432 private bool _canGetObject;
438 public virtual bool CanGetObject
442 SetPropertiesAtObjectLevel();
443 return _canGetObject;
447 if (_canGetObject != value)
449 _canGetObject = value;
450 OnPropertyChanged(nameof(CanGetObject));
455 private bool _canEditObject;
462 public virtual bool CanEditObject
466 SetPropertiesAtObjectLevel();
467 return _canEditObject;
471 if (_canEditObject != value)
473 _canEditObject = value;
474 OnPropertyChanged(nameof(CanEditObject));
479 private bool _canDeleteObject;
486 public virtual bool CanDeleteObject
490 SetPropertiesAtObjectLevel();
491 return _canDeleteObject;
495 if (_canDeleteObject != value)
497 _canDeleteObject = value;
498 OnPropertyChanged(nameof(CanDeleteObject));
503 private bool ObjectPropertiesSet;
509 private void SetPropertiesAtObjectLevel()
511 if (ObjectPropertiesSet)
513 ObjectPropertiesSet =
true;
515 Type sourceType = typeof(T);
531 public virtual async Task<T> RefreshAsync<F>(Func<Task<T>> factory)
537 result = await factory.Invoke();
555 UnhookChangedEvents(Model);
557 if (ManageObjectLifetime)
560 if (Model is ICloneable clonable)
561 savable = (
ISavable)clonable.Clone();
565 undoable.ApplyEdit();
573 HookChangedEvents(Model);
585 if (ManageObjectLifetime)
589 UnhookChangedEvents(Model);
597 HookChangedEvents(Model);
604#if (ANDROID || IOS) || XAMARIN
609 protected virtual void BeginAddNew()
612 var ibl = (Model as System.ComponentModel.IBindingList);
614 var ibl = (Model as IBindingList);
639 result = iobl.AddNew();
644 var ibl = ((IBindingList)Model);
645 result = ibl.AddNew();
658 ((IList)Model).Remove(item);
680 if (ReferenceEquals(oldValue, newValue))
return;
682 if (ManageObjectLifetime && newValue is
ISupportUndo undo)
686 if (oldValue !=
null)
688 UnhookChangedEvents(oldValue);
691 nb.BusyChanged -= Model_BusyChanged;
695 if (newValue !=
null)
697 HookChangedEvents(newValue);
700 nb.BusyChanged += Model_BusyChanged;
712 if (model is INotifyPropertyChanged npc)
713 npc.PropertyChanged -= Model_PropertyChanged;
716 ncc.ChildChanged -= Model_ChildChanged;
718 if (model is INotifyCollectionChanged cc)
719 cc.CollectionChanged -= Model_CollectionChanged;
726 private void HookChangedEvents(T model)
728 if (model is INotifyPropertyChanged npc)
729 npc.PropertyChanged += Model_PropertyChanged;
732 ncc.ChildChanged += Model_ChildChanged;
734 if (model is INotifyCollectionChanged cc)
735 cc.CollectionChanged += Model_CollectionChanged;
757 private void Model_PropertyChanged(
object sender, PropertyChangedEventArgs e)
767 private void Model_CollectionChanged(
object sender, NotifyCollectionChangedEventArgs e)
772 object IViewModel.Model
774 get {
return Model; }
775 set { Model = (T)value; }
789 PropertyChanged?.Invoke(
this,
new PropertyChangedEventArgs(propertyName));
Provides consistent context information between the client and server DataPortal objects.
Event arguments for the BusyChanged event.
string PropertyName
Property for which the Busy value has changed.
Contains event data about the changed child object.
Tracks the business rules for a business object.
static bool HasPermission(ApplicationContext applicationContext, AuthorizationActions action, Type objectType)
Checks per-type authorization rules.
ApplicationContextManager for WPF applications
static ApplicationContext GetApplicationContext()
Gets the current ApplicationContext.
Base class used to create ViewModel objects that implement their own commands/verbs/actions.
virtual void DoRemove(object item)
Removes an item from the Model (if it is a collection).
PropertyChangedEventHandler PropertyChanged
Event raised when a property changes.
virtual void OnModelChanged(T oldValue, T newValue)
Invoked when the Model changes, allowing event handlers to be unhooked from the old object and hooked...
virtual void OnSetProperties()
Override this method to hook into to logic of setting properties when model is changed or edited.
virtual void DoCancel()
Cancels changes made to the model if ManagedObjectLifetime is true.
virtual void DoDelete()
Marks the Model for deletion (if it is an editable root object).
void UnhookChangedEvents(T model)
Unhooks changed event handlers from the model.
virtual async Task< T > SaveAsync()
Saves the Model, first committing changes if ManagedObjectLifetime is true.
virtual object DoAddNew()
Adds a new item to the Model (if it is a collection).
virtual void OnPropertyChanged(string propertyName)
Raise the PropertyChanged event.
Defines the common methods required by all editable CSLA single objects.
Interface defining an object that notifies when it is busy executing an asynchronous operation.
bool IsBusy
Gets a value indicating whether the object, or any of the object's child objects, are busy running an...
Implemented by classes that notify when a child object has changed.
Defines additional elements for an ObservableCollection as required by CSLA .NET.
Specifies that the object can save itself.
Task< object > SaveAsync()
Saves the object to the database.
Define the common methods used by the UI to interact with n-level undo.
Defines the common properties required objects that track their own status.
Defines a CSLA .NET viewmodel object.
AuthorizationActions
Authorization actions.
@ PropertyChanged
Called from PropertyHasChanged event on BO but not including cascade calls by AffectedProperties