CSLA.NET 5.4.2
CSLA .NET is a software development framework that helps you build a reusable, maintainable object-oriented business layer for your app.
BusinessBindingListBase.cs
Go to the documentation of this file.
1//-----------------------------------------------------------------------
2// <copyright file="BusinessBindingListBase.cs" company="Marimer LLC">
3// Copyright (c) Marimer LLC. All rights reserved.
4// Website: https://cslanet.com
5// </copyright>
6// <summary>This is the base class from which most business collections</summary>
7//-----------------------------------------------------------------------
8using System;
9using System.ComponentModel;
10using System.Collections.Generic;
11using Csla.Properties;
12using Csla.Core;
13using System.Threading.Tasks;
14
15namespace Csla
16{
23 [System.Diagnostics.CodeAnalysis.SuppressMessage(
24 "Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")]
25 [Serializable()]
26 public abstract class BusinessBindingListBase<T, C> :
27 Core.ExtendedBindingList<C>,
28 Core.IEditableCollection, Core.IUndoableObject, ICloneable,
29 Core.ISavable, Core.ISavable<T>, Core.IParent, Server.IDataPortalTarget,
31 where T : BusinessBindingListBase<T, C>
32 where C : Core.IEditableBusinessObject
33 {
34
39 {
40 InitializeIdentity();
41 Initialize();
42 this.AllowNew = true;
43 }
44
45
46#region Initialize
47
53 protected virtual void Initialize()
54 { /* allows subclass to initialize events before any other activity occurs */ }
55
56 #endregion
57
58 #region Identity
59
60 private int _identity = -1;
61
63 {
64 get { return _identity; }
65 }
66
67 private void InitializeIdentity()
68 {
69 _identity = ((IParent)this).GetNextIdentity(_identity);
70 }
71
72 [NonSerialized]
73 [NotUndoable]
74 private IdentityManager _identityManager;
75
76 int IParent.GetNextIdentity(int current)
77 {
78 if (this.Parent != null)
79 {
80 return this.Parent.GetNextIdentity(current);
81 }
82 else
83 {
84 if (_identityManager == null)
85 _identityManager = new IdentityManager();
86 return _identityManager.GetNextIdentity(current);
87 }
88 }
89
90 #endregion
91
92 #region IsDirty, IsValid, IsSavable
93
97 bool Core.ITrackStatus.IsSelfDirty
98 {
99 get { return IsDirty; }
100 }
101
105 [Browsable(false)]
106 [System.ComponentModel.DataAnnotations.Display(AutoGenerateField = false)]
107 [System.ComponentModel.DataAnnotations.ScaffoldColumn(false)]
108 public bool IsDirty
109 {
110 get
111 {
112 // any non-new deletions make us dirty
113 foreach (C item in DeletedList)
114 if (!item.IsNew)
115 return true;
116
117 // run through all the child objects
118 // and if any are dirty then then
119 // collection is dirty
120 foreach (C child in this)
121 if (child.IsDirty)
122 return true;
123 return false;
124 }
125 }
126
127 bool Core.ITrackStatus.IsSelfValid
128 {
129 get { return IsSelfValid; }
130 }
131
136 protected virtual bool IsSelfValid
137 {
138 get { return IsValid; }
139 }
140
145 [Browsable(false)]
146 [System.ComponentModel.DataAnnotations.Display(AutoGenerateField = false)]
147 [System.ComponentModel.DataAnnotations.ScaffoldColumn(false)]
148 public virtual bool IsValid
149 {
150 get
151 {
152 // run through all the child objects
153 // and if any are invalid then the
154 // collection is invalid
155 foreach (C child in this)
156 if (!child.IsValid)
157 return false;
158 return true;
159 }
160 }
161
166 [Browsable(false)]
167 [System.ComponentModel.DataAnnotations.Display(AutoGenerateField = false)]
168 public virtual bool IsSavable
169 {
170 get
171 {
172 bool auth = Csla.Rules.BusinessRules.HasPermission(Rules.AuthorizationActions.EditObject, this);
173 return (IsDirty && IsValid && auth && !IsBusy);
174 }
175 }
176
177#endregion
178
179#region Begin/Cancel/ApplyEdit
180
201 public void BeginEdit()
202 {
203 if (this.IsChild)
204 throw new NotSupportedException(Resources.NoBeginEditChildException);
205
206 CopyState(this.EditLevel + 1);
207 }
208
222 public void CancelEdit()
223 {
224 if (this.IsChild)
225 throw new NotSupportedException(Resources.NoCancelEditChildException);
226
227 UndoChanges(this.EditLevel - 1);
228 }
229
243 public void ApplyEdit()
244 {
245 if (this.IsChild)
246 throw new NotSupportedException(Resources.NoApplyEditChildException);
247
248 AcceptChanges(this.EditLevel - 1);
249 }
250
251 void Core.IParent.ApplyEditChild(Core.IEditableBusinessObject child)
252 {
253 EditChildComplete(child);
254 }
255
257 {
258 get { return this.Parent; }
259 }
266 protected virtual void EditChildComplete(Core.IEditableBusinessObject child)
267 {
268
269 // do nothing, we don't really care
270 // when a child has its edits applied
271 }
272
273#endregion
274
275#region N-level undo
276
277 void Core.IUndoableObject.CopyState(int parentEditLevel, bool parentBindingEdit)
278 {
279 if (!parentBindingEdit)
280 CopyState(parentEditLevel);
281 }
282
283 void Core.IUndoableObject.UndoChanges(int parentEditLevel, bool parentBindingEdit)
284 {
285 if (!parentBindingEdit)
286 UndoChanges(parentEditLevel);
287 }
288
289 void Core.IUndoableObject.AcceptChanges(int parentEditLevel, bool parentBindingEdit)
290 {
291 if (!parentBindingEdit)
292 AcceptChanges(parentEditLevel);
293 }
294
295 private void CopyState(int parentEditLevel)
296 {
297 if (this.EditLevel + 1 > parentEditLevel)
298 throw new UndoException(string.Format(Resources.EditLevelMismatchException, "CopyState"), this.GetType().Name, _parent != null ? _parent.GetType().Name : null, this.EditLevel, parentEditLevel - 1);
299
300 // we are going a level deeper in editing
301 _editLevel += 1;
302
303 // cascade the call to all child objects
304 foreach (C child in this)
305 child.CopyState(_editLevel, false);
306
307 // cascade the call to all deleted child objects
308 foreach (C child in DeletedList)
309 child.CopyState(_editLevel, false);
310 }
311
312 private bool _completelyRemoveChild;
313
314 private void UndoChanges(int parentEditLevel)
315 {
316 C child;
317
318 if (this.EditLevel - 1 != parentEditLevel)
319 throw new UndoException(string.Format(Resources.EditLevelMismatchException, "UndoChanges"), this.GetType().Name, _parent != null ? _parent.GetType().Name : null, this.EditLevel, parentEditLevel + 1);
320
321 // we are coming up one edit level
322 _editLevel -= 1;
323 if (_editLevel < 0) _editLevel = 0;
324
325 try
326 {
327 using (LoadListMode)
328 {
329 // Cancel edit on all current items
330 for (int index = Count - 1; index >= 0; index--)
331 {
332 child = this[index];
333
334 child.UndoChanges(_editLevel, false);
335
336 // if item is below its point of addition, remove
337 if (child.EditLevelAdded > _editLevel)
338 {
339 bool oldAllowRemove = this.AllowRemove;
340 try
341 {
342 this.AllowRemove = true;
343 _completelyRemoveChild = true;
344 RemoveAt(index);
345 }
346 finally
347 {
348 _completelyRemoveChild = false;
349 this.AllowRemove = oldAllowRemove;
350 }
351 }
352 }
353
354 // cancel edit on all deleted items
355 for (int index = DeletedList.Count - 1; index >= 0; index--)
356 {
357 child = DeletedList[index];
358 child.UndoChanges(_editLevel, false);
359 if (child.EditLevelAdded > _editLevel)
360 {
361 // if item is below its point of addition, remove
362 DeletedList.RemoveAt(index);
363 }
364 else
365 {
366 // if item is no longer deleted move back to main list
367 if (!child.IsDeleted) UnDeleteChild(child);
368 }
369 }
370 }
371 }
372 finally
373 {
374 OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
375 }
376 }
377
378 private void AcceptChanges(int parentEditLevel)
379 {
380 if (this.EditLevel - 1 != parentEditLevel)
381 throw new UndoException(string.Format(Resources.EditLevelMismatchException, "AcceptChanges"), this.GetType().Name, _parent != null ? _parent.GetType().Name : null, this.EditLevel, parentEditLevel + 1);
382
383 // we are coming up one edit level
384 _editLevel -= 1;
385 if (_editLevel < 0) _editLevel = 0;
386
387 // cascade the call to all child objects
388 foreach (C child in this)
389 {
390 child.AcceptChanges(_editLevel, false);
391 // if item is below its point of addition, lower point of addition
392 if (child.EditLevelAdded > _editLevel) child.EditLevelAdded = _editLevel;
393 }
394
395 // cascade the call to all deleted child objects
396 for (int index = DeletedList.Count - 1; index >= 0; index--)
397 {
398 C child = DeletedList[index];
399 child.AcceptChanges(_editLevel, false);
400 // if item is below its point of addition, remove
401 if (child.EditLevelAdded > _editLevel)
402 DeletedList.RemoveAt(index);
403 }
404 }
405
406#endregion
407
408#region Delete and Undelete child
409
410 private MobileList<C> _deletedList;
411
416 [System.Diagnostics.CodeAnalysis.SuppressMessage(
417 "Microsoft.Design", "CA1002:DoNotExposeGenericLists")]
418 [EditorBrowsable(EditorBrowsableState.Advanced)]
420 {
421 get
422 {
423 if (_deletedList == null)
424 _deletedList = new MobileList<C>();
425 return _deletedList;
426 }
427 }
428
429 private void DeleteChild(C child)
430 {
431 // set child edit level
432 Core.UndoableBase.ResetChildEditLevel(child, this.EditLevel, false);
433 // mark the object as deleted
434 child.DeleteChild();
435 // and add it to the deleted collection for storage
436 DeletedList.Add(child);
437 }
438
439 private void UnDeleteChild(C child)
440 {
441 // since the object is no longer deleted, remove it from
442 // the deleted collection
443 DeletedList.Remove(child);
444
445 // we are inserting an _existing_ object so
446 // we need to preserve the object's editleveladded value
447 // because it will be changed by the normal add process
448 int saveLevel = child.EditLevelAdded;
449 Add(child);
450 child.EditLevelAdded = saveLevel;
451 }
452
458 [EditorBrowsable(EditorBrowsableState.Advanced)]
459 public bool ContainsDeleted(C item)
460 {
461 return DeletedList.Contains(item);
462 }
463
464#endregion
465
466#region Insert, Remove, Clear
467
472 protected override object AddNewCore()
473 {
474 var item = DataPortal.CreateChild<C>();
475 Add(item);
476 return item;
477 }
478
484 void Core.IEditableCollection.RemoveChild(Csla.Core.IEditableBusinessObject child)
485 {
486 Remove((C)child);
487 }
488
490 {
491 return DeletedList;
492 }
493
499 void Core.IParent.RemoveChild(Csla.Core.IEditableBusinessObject child)
500 {
501 Remove((C)child);
502 }
503
509 protected override void InsertItem(int index, C item)
510 {
511 // set parent reference
512 item.SetParent(this);
513 // set child edit level
514 Core.UndoableBase.ResetChildEditLevel(item, this.EditLevel, false);
515 // when an object is inserted we assume it is
516 // a new object and so the edit level when it was
517 // added must be set
518 item.EditLevelAdded = _editLevel;
519 base.InsertItem(index, item);
520 }
521
527 protected override void RemoveItem(int index)
528 {
529 // when an object is 'removed' it is really
530 // being deleted, so do the deletion work
531 C child = this[index];
532 using (LoadListMode)
533 {
534 base.RemoveItem(index);
535 }
536 if (!_completelyRemoveChild)
537 {
538 // the child shouldn't be completely removed,
539 // so copy it to the deleted list
540 DeleteChild(child);
541 }
542 if (RaiseListChangedEvents)
543 OnListChanged(new ListChangedEventArgs(ListChangedType.ItemDeleted, index));
544 }
545
550 protected override void ClearItems()
551 {
552 while (base.Count > 0)
553 RemoveItem(0);
554 base.ClearItems();
555 }
556
568 protected override void SetItem(int index, C item)
569 {
570 C child = default(C);
571 if (!(ReferenceEquals((C)(this[index]), item)))
572 child = this[index];
573 // replace the original object with this new
574 // object
575 using (LoadListMode)
576 {
577 // set parent reference
578 item.SetParent(this);
579 // set child edit level
580 Core.UndoableBase.ResetChildEditLevel(item, this.EditLevel, false);
581 // reset EditLevelAdded
582 item.EditLevelAdded = this.EditLevel;
583
584 // add to list
585 base.SetItem(index, item);
586 }
587 if (child != null)
588 DeleteChild(child);
589 if (RaiseListChangedEvents)
590 OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, index));
591 }
592
593#endregion
594
595#region Cascade child events
596
602 [EditorBrowsable(EditorBrowsableState.Never)]
603 protected override void Child_PropertyChanged(object sender, PropertyChangedEventArgs e)
604 {
605 if (_deserialized && RaiseListChangedEvents && e != null)
606 {
607 for (int index = 0; index < Count; index++)
608 {
609 if (ReferenceEquals(this[index], sender))
610 {
611 PropertyDescriptor descriptor = GetPropertyDescriptor(e.PropertyName);
612 if (descriptor != null)
613 OnListChanged(new ListChangedEventArgs(
614 ListChangedType.ItemChanged, index, descriptor));
615 else
616 OnListChanged(new ListChangedEventArgs(
617 ListChangedType.ItemChanged, index));
618 }
619 }
620 }
621 base.Child_PropertyChanged(sender, e);
622 }
623
624 private static PropertyDescriptorCollection _propertyDescriptors;
625
626 private PropertyDescriptor GetPropertyDescriptor(string propertyName)
627 {
628 if (_propertyDescriptors == null)
629 _propertyDescriptors = TypeDescriptor.GetProperties(typeof(C));
630 PropertyDescriptor result = null;
631 foreach (PropertyDescriptor desc in _propertyDescriptors)
632 if (desc.Name == propertyName)
633 {
634 result = desc;
635 break;
636 }
637 return result;
638 }
639
640#endregion
641
642#region Edit level tracking
643
644 // keep track of how many edit levels we have
645 private int _editLevel;
646
650 [EditorBrowsable(EditorBrowsableState.Never)]
651 protected int EditLevel
652 {
653 get { return _editLevel; }
654 }
655
656 int Core.IUndoableObject.EditLevel
657 {
658 get
659 {
660 return this.EditLevel;
661 }
662 }
663
664#endregion
665
666#region IsChild
667
668 [NotUndoable()]
669 private bool _isChild = false;
670
675 [Browsable(false)]
676 [System.ComponentModel.DataAnnotations.Display(AutoGenerateField = false)]
677 [System.ComponentModel.DataAnnotations.ScaffoldColumn(false)]
678 public bool IsChild
679 {
680 get { return _isChild; }
681 }
682
700 protected void MarkAsChild()
701 {
702 _identity = -1;
703 _isChild = true;
704 }
705
706#endregion
707
708#region ICloneable
709
710 object ICloneable.Clone()
711 {
712 return GetClone();
713 }
714
719 [EditorBrowsable(EditorBrowsableState.Advanced)]
720 protected virtual object GetClone()
721 {
722 return Core.ObjectCloner.Clone(this);
723 }
724
729 public T Clone()
730 {
731 return (T)GetClone();
732 }
733
734#endregion
735
736#region Serialization Notification
737
738 [NonSerialized]
739 [NotUndoable]
740 private bool _deserialized = false;
741
746 [EditorBrowsable(EditorBrowsableState.Advanced)]
747 protected override void OnDeserialized()
748 {
749 _deserialized = true;
750 base.OnDeserialized();
751
752 foreach (Core.IEditableBusinessObject child in this)
753 {
754 child.SetParent(this);
755 }
756
757 foreach (Core.IEditableBusinessObject child in DeletedList)
758 child.SetParent(this);
759 }
760
761#endregion
762
763#region Child Data Access
764
769 [EditorBrowsable(EditorBrowsableState.Advanced)]
770 protected virtual void Child_Create()
771 { /* do nothing - list self-initializes */ }
772
782 [EditorBrowsable(EditorBrowsableState.Advanced)]
783 protected virtual void Child_Update(params object[] parameters)
784 {
785 using (LoadListMode)
786 {
787 foreach (var child in DeletedList)
788 DataPortal.UpdateChild(child, parameters);
789 DeletedList.Clear();
790
791 foreach (var child in this)
792 if (child.IsDirty) DataPortal.UpdateChild(child, parameters);
793 }
794 }
795
796#endregion
797
798#region Data Access
799
827 public T Save()
828 {
829 try
830 {
831 return SaveAsync(null, true).Result;
832 }
833 catch (AggregateException ex)
834 {
835 if (ex.InnerExceptions.Count > 0)
836 throw ex.InnerExceptions[0];
837 else
838 throw;
839 }
840 }
841
845 public async Task<T> SaveAsync()
846 {
847 return await SaveAsync(null, false);
848 }
849
855 public Task SaveAndMergeAsync()
856 {
857 throw new NotSupportedException(nameof(SaveAndMergeAsync));
858 }
859
865 protected virtual async Task<T> SaveAsync(object userState, bool isSync)
866 {
867 T result;
868 if (this.IsChild)
869 throw new InvalidOperationException(Resources.NoSaveChildException);
870
871 if (_editLevel > 0)
872 throw new InvalidOperationException(Resources.NoSaveEditingException);
873
874 if (!IsValid)
875 throw new Rules.ValidationException(Resources.NoSaveInvalidException);
876
877 if (IsBusy)
878 throw new InvalidOperationException(Resources.BusyObjectsMayNotBeSaved);
879
880 if (IsDirty)
881 {
882 if (isSync)
883 {
884 result = DataPortal.Update<T>((T)this);
885 }
886 else
887 {
888 result = await DataPortal.UpdateAsync<T>((T)this);
889 }
890 }
891 else
892 {
893 result = (T)this;
894 }
895 OnSaved(result, null, userState);
896 return result;
897 }
898
902 [Obsolete]
903 public void BeginSave()
904 {
905 BeginSave(null, null);
906 }
907
912 [Obsolete]
913 public void BeginSave(object userState)
914 {
915 BeginSave(null, userState);
916 }
917
924 [Obsolete]
925 public void BeginSave(EventHandler<SavedEventArgs> handler)
926 {
927 BeginSave(handler, null);
928 }
929
937 [Obsolete]
938 public async void BeginSave(EventHandler<SavedEventArgs> handler, object userState)
939 {
940 T result = default(T);
941 Exception error = null;
942 try
943 {
944 result = await SaveAsync(userState, false);
945 }
946 catch (AggregateException ex)
947 {
948 if (ex.InnerExceptions.Count > 0)
949 error = ex.InnerExceptions[0];
950 else
951 error = ex;
952 }
953 catch (Exception ex)
954 {
955 error = ex;
956 }
957 if (handler != null)
958 handler(this, new SavedEventArgs(result, error, userState));
959 }
960
966 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", MessageId = "Member")]
967 [EditorBrowsable(EditorBrowsableState.Advanced)]
969 {
970
971 }
972
978 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", MessageId = "Member")]
979 [EditorBrowsable(EditorBrowsableState.Advanced)]
981 {
982
983 }
984
991 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", MessageId = "Member")]
992 [EditorBrowsable(EditorBrowsableState.Advanced)]
993 protected virtual void DataPortal_OnDataPortalException(DataPortalEventArgs e, Exception ex)
994 {
995
996 }
997
1003 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", MessageId = "Member")]
1004 [EditorBrowsable(EditorBrowsableState.Advanced)]
1006 {
1007 }
1008
1014 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", MessageId = "Member")]
1015 [EditorBrowsable(EditorBrowsableState.Advanced)]
1017 {
1018 }
1019
1026 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", MessageId = "Member")]
1027 [EditorBrowsable(EditorBrowsableState.Advanced)]
1028 protected virtual void Child_OnDataPortalException(DataPortalEventArgs e, Exception ex)
1029 {
1030 }
1031
1032#endregion
1033
1034#region ISavable Members
1035
1036 object Csla.Core.ISavable.Save()
1037 {
1038 return Save();
1039 }
1040
1041 object Csla.Core.ISavable.Save(bool forceUpdate)
1042 {
1043 return Save();
1044 }
1045
1046 async Task<object> ISavable.SaveAsync()
1047 {
1048 return await SaveAsync();
1049 }
1050
1051 async Task<object> ISavable.SaveAsync(bool forceUpdate)
1052 {
1053 return await SaveAsync();
1054 }
1055
1056 async Task ISavable.SaveAndMergeAsync(bool forceUpdate)
1057 {
1058 await SaveAndMergeAsync();
1059 }
1060
1061 void Csla.Core.ISavable.SaveComplete(object newObject)
1062 {
1063 OnSaved((T)newObject, null, null);
1064 }
1065
1066 T Csla.Core.ISavable<T>.Save(bool forceUpdate)
1067 {
1068 return Save();
1069 }
1070
1071 async Task<T> ISavable<T>.SaveAsync(bool forceUpdate)
1072 {
1073 return await SaveAsync();
1074 }
1075
1076 async Task ISavable<T>.SaveAndMergeAsync(bool forceUpdate)
1077 {
1078 await SaveAndMergeAsync();
1079 }
1080
1081 void Csla.Core.ISavable<T>.SaveComplete(T newObject)
1082 {
1083 OnSaved(newObject, null, null);
1084 }
1085
1086 [NonSerialized()]
1087 [NotUndoable]
1088 private EventHandler<Csla.Core.SavedEventArgs> _nonSerializableSavedHandlers;
1089 [NotUndoable]
1090 private EventHandler<Csla.Core.SavedEventArgs> _serializableSavedHandlers;
1091
1095 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design",
1096 "CA1062:ValidateArgumentsOfPublicMethods")]
1097 public event EventHandler<Csla.Core.SavedEventArgs> Saved
1098 {
1099 add
1100 {
1101 if (value.Method.IsPublic &&
1102 (value.Method.DeclaringType.IsSerializable ||
1103 value.Method.IsStatic))
1104 _serializableSavedHandlers = (EventHandler<Csla.Core.SavedEventArgs>)
1105 System.Delegate.Combine(_serializableSavedHandlers, value);
1106 else
1107 _nonSerializableSavedHandlers = (EventHandler<Csla.Core.SavedEventArgs>)
1108 System.Delegate.Combine(_nonSerializableSavedHandlers, value);
1109 }
1110 remove
1111 {
1112 if (value.Method.IsPublic &&
1113 (value.Method.DeclaringType.IsSerializable ||
1114 value.Method.IsStatic))
1115 _serializableSavedHandlers = (EventHandler<Csla.Core.SavedEventArgs>)
1116 System.Delegate.Remove(_serializableSavedHandlers, value);
1117 else
1118 _nonSerializableSavedHandlers = (EventHandler<Csla.Core.SavedEventArgs>)
1119 System.Delegate.Remove(_nonSerializableSavedHandlers, value);
1120 }
1121 }
1122
1131 [System.ComponentModel.EditorBrowsable(EditorBrowsableState.Advanced)]
1132 protected virtual void OnSaved(T newObject, Exception e, object userState)
1133 {
1134 Csla.Core.SavedEventArgs args = new Csla.Core.SavedEventArgs(newObject, e, userState);
1135 if (_nonSerializableSavedHandlers != null)
1136 _nonSerializableSavedHandlers.Invoke(this, args);
1137 if (_serializableSavedHandlers != null)
1138 _serializableSavedHandlers.Invoke(this, args);
1139 }
1140
1141#endregion
1142
1143#region Parent/Child link
1144
1145 [NotUndoable(), NonSerialized()]
1146 private Core.IParent _parent;
1147
1155 [Browsable(false)]
1156 [System.ComponentModel.DataAnnotations.Display(AutoGenerateField = false)]
1157 [System.ComponentModel.DataAnnotations.ScaffoldColumn(false)]
1158 [EditorBrowsable(EditorBrowsableState.Advanced)]
1159 public Core.IParent Parent
1160 {
1161 get
1162 {
1163 return _parent;
1164 }
1165 }
1166
1173 protected virtual void SetParent(Core.IParent parent)
1174 {
1175 _parent = parent;
1176 _identityManager = null;
1177 InitializeIdentity();
1178 }
1179
1186 void Core.IEditableCollection.SetParent(Core.IParent parent)
1187 {
1188 this.SetParent(parent);
1189 }
1190
1191#endregion
1192
1193#region ToArray
1194
1198 public C[] ToArray()
1199 {
1200 List<C> result = new List<C>();
1201 foreach (C item in this)
1202 result.Add(item);
1203 return result.ToArray();
1204 }
1205#endregion
1206
1207#region ITrackStatus
1208
1209 bool Core.ITrackStatus.IsNew
1210 {
1211 get
1212 {
1213 return false;
1214 }
1215 }
1216
1217 bool Core.ITrackStatus.IsDeleted
1218 {
1219 get
1220 {
1221 return false;
1222 }
1223 }
1224
1228 [Browsable(false)]
1229 [System.ComponentModel.DataAnnotations.Display(AutoGenerateField = false)]
1230 [System.ComponentModel.DataAnnotations.ScaffoldColumn(false)]
1231 public override bool IsBusy
1232 {
1233 get
1234 {
1235 // any non-new deletions make us dirty
1236 foreach (C item in DeletedList)
1237 if (item.IsBusy)
1238 return true;
1239
1240 // run through all the child objects
1241 // and if any are dirty then then
1242 // collection is dirty
1243 foreach (C child in this)
1244 if (child.IsBusy)
1245 return true;
1246
1247 return false;
1248 }
1249 }
1250
1251#endregion
1252
1253#region IDataPortalTarget Members
1254
1255 void Csla.Server.IDataPortalTarget.CheckRules()
1256 { }
1257
1258 void Csla.Server.IDataPortalTarget.MarkAsChild()
1259 {
1260 this.MarkAsChild();
1261 }
1262
1263 void Csla.Server.IDataPortalTarget.MarkNew()
1264 { }
1265
1266 void Csla.Server.IDataPortalTarget.MarkOld()
1267 { }
1268
1269 void Csla.Server.IDataPortalTarget.DataPortal_OnDataPortalInvoke(DataPortalEventArgs e)
1270 {
1272 }
1273
1274 void Csla.Server.IDataPortalTarget.DataPortal_OnDataPortalInvokeComplete(DataPortalEventArgs e)
1275 {
1277 }
1278
1279 void Csla.Server.IDataPortalTarget.DataPortal_OnDataPortalException(DataPortalEventArgs e, Exception ex)
1280 {
1282 }
1283
1284 void Csla.Server.IDataPortalTarget.Child_OnDataPortalInvoke(DataPortalEventArgs e)
1285 {
1287 }
1288
1289 void Csla.Server.IDataPortalTarget.Child_OnDataPortalInvokeComplete(DataPortalEventArgs e)
1290 {
1292 }
1293
1294 void Csla.Server.IDataPortalTarget.Child_OnDataPortalException(DataPortalEventArgs e, Exception ex)
1295 {
1296 this.Child_OnDataPortalException(e, ex);
1297 }
1298
1299#endregion
1300
1301#region Mobile object overrides
1302
1310 [System.ComponentModel.EditorBrowsable(EditorBrowsableState.Advanced)]
1312 {
1313 _isChild = info.GetValue<bool>("Csla.BusinessListBase._isChild");
1314 _editLevel = info.GetValue<int>("Csla.BusinessListBase._editLevel");
1315 _identity = info.GetValue<int>("Csla.Core.BusinessBase._identity");
1316 base.OnSetState(info);
1317 }
1318
1326 [System.ComponentModel.EditorBrowsable(EditorBrowsableState.Advanced)]
1328 {
1329 info.AddValue("Csla.BusinessListBase._isChild", _isChild);
1330 info.AddValue("Csla.BusinessListBase._editLevel", _editLevel);
1331 info.AddValue("Csla.Core.BusinessBase._identity", _identity);
1332 base.OnGetState(info);
1333 }
1334
1345 [System.ComponentModel.EditorBrowsable(EditorBrowsableState.Advanced)]
1347 {
1348 base.OnGetChildren(info, formatter);
1349 if (_deletedList != null)
1350 {
1351 var fieldManagerInfo = formatter.SerializeObject(_deletedList);
1352 info.AddChild("_deletedList", fieldManagerInfo.ReferenceId);
1353 }
1354 }
1355
1366 [System.ComponentModel.EditorBrowsable(EditorBrowsableState.Advanced)]
1368 {
1369 if (info.Children.ContainsKey("_deletedList"))
1370 {
1371 var childData = info.Children["_deletedList"];
1372 _deletedList = (MobileList<C>)formatter.GetObject(childData.ReferenceId);
1373 }
1374 base.OnSetChildren(info, formatter);
1375 }
1376
1377#endregion
1378 }
1379}
This is the base class from which most business collections or lists will be derived.
virtual object GetClone()
Creates a clone of the object.
virtual void Initialize()
Override this method to set up event handlers so user code in a partial class can respond to events r...
void CancelEdit()
Cancels the current edit process, restoring the object's state to its previous values.
override void RemoveItem(int index)
Marks the child object for deletion and moves it to the collection of deleted objects.
void MarkAsChild()
Marks the object as being a child object.
override void OnSetState(Csla.Serialization.Mobile.SerializationInfo info)
Override this method to retrieve your field values from the MobileFormatter serialzation stream.
virtual async Task< T > SaveAsync(object userState, bool isSync)
Saves the object to the database.
void BeginSave()
Starts an async operation to save the object to the database.
Task SaveAndMergeAsync()
Saves the object to the database, merging any resulting updates into the existing object graph.
virtual void DataPortal_OnDataPortalException(DataPortalEventArgs e, Exception ex)
Called by the server-side DataPortal if an exception occurs during data access.
bool IsDirty
Gets a value indicating whether this object's data has been changed.
void BeginSave(EventHandler< SavedEventArgs > handler)
Starts an async operation to save the object to the database.
override void SetItem(int index, C item)
Replaces the item at the specified index with the specified item, first moving the original item to t...
EventHandler< Csla.Core.SavedEventArgs > Saved
Event raised when an object has been saved.
override void OnDeserialized()
This method is called on a newly deserialized object after deserialization is complete.
async void BeginSave(EventHandler< SavedEventArgs > handler, object userState)
Starts an async operation to save the object to the database.
bool ContainsDeleted(C item)
Returns true if the internal deleted list contains the specified child object.
virtual void SetParent(Core.IParent parent)
Used by BusinessListBase as a child object is created to tell the child object about its parent.
override void InsertItem(int index, C item)
Sets the edit level of the child object as it is added.
virtual void Child_OnDataPortalInvokeComplete(DataPortalEventArgs e)
Called by the server-side DataPortal after calling the requested DataPortal_XYZ method.
virtual void DataPortal_OnDataPortalInvoke(DataPortalEventArgs e)
Called by the server-side DataPortal prior to calling the requested DataPortal_xyz method.
MobileList< C > DeletedList
A collection containing all child objects marked for deletion.
async Task< T > SaveAsync()
Saves the object to the database.
int EditLevel
Returns the current edit level of the object.
T Save()
Saves the object to the database.
virtual void EditChildComplete(Core.IEditableBusinessObject child)
Override this method to be notified when a child object's Core.BusinessBase.ApplyEdit method has comp...
C[] ToArray()
Get an array containing all items in the list.
void BeginEdit()
Starts a nested edit on the object.
virtual void DataPortal_OnDataPortalInvokeComplete(DataPortalEventArgs e)
Called by the server-side DataPortal after calling the requested DataPortal_xyz method.
virtual bool IsSavable
Returns true if this object is both dirty and valid.
override void Child_PropertyChanged(object sender, PropertyChangedEventArgs e)
Handles any PropertyChanged event from a child object and echoes it up as a ListChanged event.
override void OnGetChildren(Csla.Serialization.Mobile.SerializationInfo info, Csla.Serialization.Mobile.MobileFormatter formatter)
Override this method to insert child objects into the MobileFormatter serialization stream.
override void ClearItems()
Clears the collection, moving all active items to the deleted list.
bool IsChild
Indicates whether this collection object is a child object.
virtual bool IsValid
Gets a value indicating whether this object is currently in a valid state (has no broken validation r...
override object AddNewCore()
Override this method to create a new object that is added to the collection.
override bool IsBusy
Gets the busy status for this object and its child objects.
BusinessBindingListBase()
Creates an instance of the object.
virtual void Child_OnDataPortalException(DataPortalEventArgs e, Exception ex)
Called by the server-side DataPortal if an exception occurs during data access.
virtual void Child_Update(params object[] parameters)
Saves all items in the list, automatically performing insert, update or delete operations as necessar...
T Clone()
Creates a clone of the object.
virtual void Child_Create()
Initializes a new instance of the object with default values.
void BeginSave(object userState)
Starts an async operation to save the object to the database.
virtual void OnSaved(T newObject, Exception e, object userState)
Raises the Saved event, indicating that the object has been saved, and providing a reference to the n...
override void OnSetChildren(Csla.Serialization.Mobile.SerializationInfo info, Csla.Serialization.Mobile.MobileFormatter formatter)
Override this method to get child objects from the MobileFormatter serialization stream.
void ApplyEdit()
Commits the current edit process.
virtual void Child_OnDataPortalInvoke(DataPortalEventArgs e)
Called by the server-side DataPortal prior to calling the requested DataPortal_XYZ method.
override void OnGetState(Csla.Serialization.Mobile.SerializationInfo info)
Override this method to insert your field values into the MobileFormatter serialzation stream.
Extends BindingList of T by adding extra behaviors.
Used by the root object in a graph to manage the object instance identity values for the graph.
int GetNextIdentity(int current)
Gets and consumes the next available unique identity value for an object instance in the object graph...
Implements a list that is serializable using the SerializationFormatterFactory.GetFormatter().
Definition: MobileList.cs:29
virtual void OnSetChildren(SerializationInfo info, MobileFormatter formatter)
Override this method to manually deserialize child objects from data in the serialization stream.
Definition: MobileList.cs:117
Event arguments containing a reference to the new object that was returned as a result of the Save() ...
Exception indicating a problem with the use of the n-level undo feature in CSLA .NET.
Provides information about the DataPortal call.
This is the client-side DataPortal.
Definition: DataPortalT.cs:24
T Update(T obj)
Called by a factory method in a business class or by the UI to update an object.
Definition: DataPortalT.cs:715
static void UpdateChild(object child)
Inserts, updates or deletes an existing child business object.
Definition: DataPortal.cs:733
async Task< T > UpdateAsync(T obj)
Called by a factory method in a business class or by the UI to update an object.
Definition: DataPortalT.cs:773
A strongly-typed resource class, for looking up localized strings, etc.
static string BusyObjectsMayNotBeSaved
Looks up a localized string similar to Objects that are marked busy may not be saved.
static string EditLevelMismatchException
Looks up a localized string similar to Edit level mismatch in {0}.
static string NoSaveEditingException
Looks up a localized string similar to Object is still being edited and can not be saved.
static string NoApplyEditChildException
Looks up a localized string similar to ApplyEdit is not valid on a child object.
static string NoBeginEditChildException
Looks up a localized string similar to BeginEdit is not valid on a child object.
static string NoCancelEditChildException
Looks up a localized string similar to CancelEdit is not valid on a child object.
static string NoSaveInvalidException
Looks up a localized string similar to Object is not valid and can not be saved.
static string NoSaveChildException
Looks up a localized string similar to Can not directly save a child object.
Tracks the business rules for a business object.
static bool HasPermission(AuthorizationActions action, Type objectType)
Checks per-type authorization rules.
Serializes and deserializes objects at the field level.
Object containing the serialization data for a specific object.
This is the core interface implemented by all CSLA .NET base classes.
int Identity
Gets a value representing this object instance's unique identity value within the business object gra...
Defines the common methods required by all editable CSLA single objects.
Defines the common methods required by all editable CSLA collection objects.
object GetDeletedList()
Used by ObjectFactory to gain access to the list of deleted items contained in the collection.
Interface defining an object that notifies when it is busy executing an asynchronous operation.
Definition: INotifyBusy.cs:17
Defines the interface that must be implemented by any business object that contains child objects.
Definition: IParent.cs:18
int GetNextIdentity(int current)
Gets and consumes the next available unique identity value for an object instance in the object graph...
IParent Parent
Provide access to the parent reference for use in child object code.
Definition: IParent.cs:39
Specifies that the object can save itself.
Definition: ISavableT.cs:19
void SaveComplete(object newObject)
INTERNAL CSLA .NET USE ONLY.
Task SaveAndMergeAsync()
Saves the object to the database, merging the result into the original object graph
object Save()
Saves the object to the database.
Task< object > SaveAsync()
Saves the object to the database.
Defines the methods required to participate in n-level undo within the CSLA .NET framework.
@ Serializable
Prevents updating or inserting until the transaction is complete.