CSLA.NET 6.0.0
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> :
28 Core.IEditableCollection, Core.IUndoableObject, ICloneable,
29 Core.ISavable, Core.ISavable<T>, Core.IParent, Server.IDataPortalTarget,
32 where T : BusinessBindingListBase<T, C>
33 where C : Core.IEditableBusinessObject
34 {
35
40 {
41 }
42
46 protected ApplicationContext ApplicationContext { get; private set; }
48 {
49 get => ApplicationContext;
50 set
51 {
52 ApplicationContext = value;
53 InitializeIdentity();
54 Initialize();
55 this.AllowNew = true;
56 }
57 }
58
59
60 #region Initialize
61
67 protected virtual void Initialize()
68 { /* allows subclass to initialize events before any other activity occurs */ }
69
70 #endregion
71
72 #region Identity
73
74 private int _identity = -1;
75
77 {
78 get { return _identity; }
79 }
80
81 private void InitializeIdentity()
82 {
83 _identity = ((IParent)this).GetNextIdentity(_identity);
84 }
85
86 [NonSerialized]
87 [NotUndoable]
88 private IdentityManager _identityManager;
89
90 int IParent.GetNextIdentity(int current)
91 {
92 if (this.Parent != null)
93 {
94 return this.Parent.GetNextIdentity(current);
95 }
96 else
97 {
98 if (_identityManager == null)
99 _identityManager = new IdentityManager();
100 return _identityManager.GetNextIdentity(current);
101 }
102 }
103
104 #endregion
105
106 #region IsDirty, IsValid, IsSavable
107
111 bool Core.ITrackStatus.IsSelfDirty
112 {
113 get { return IsDirty; }
114 }
115
119 [Browsable(false)]
120 [System.ComponentModel.DataAnnotations.Display(AutoGenerateField = false)]
121 [System.ComponentModel.DataAnnotations.ScaffoldColumn(false)]
122 public bool IsDirty
123 {
124 get
125 {
126 // any non-new deletions make us dirty
127 foreach (C item in DeletedList)
128 if (!item.IsNew)
129 return true;
130
131 // run through all the child objects
132 // and if any are dirty then then
133 // collection is dirty
134 foreach (C child in this)
135 if (child.IsDirty)
136 return true;
137 return false;
138 }
139 }
140
141 bool Core.ITrackStatus.IsSelfValid
142 {
143 get { return IsSelfValid; }
144 }
145
150 protected virtual bool IsSelfValid
151 {
152 get { return IsValid; }
153 }
154
159 [Browsable(false)]
160 [System.ComponentModel.DataAnnotations.Display(AutoGenerateField = false)]
161 [System.ComponentModel.DataAnnotations.ScaffoldColumn(false)]
162 public virtual bool IsValid
163 {
164 get
165 {
166 // run through all the child objects
167 // and if any are invalid then the
168 // collection is invalid
169 foreach (C child in this)
170 if (!child.IsValid)
171 return false;
172 return true;
173 }
174 }
175
180 [Browsable(false)]
181 [System.ComponentModel.DataAnnotations.Display(AutoGenerateField = false)]
182 public virtual bool IsSavable
183 {
184 get
185 {
186 bool auth = Csla.Rules.BusinessRules.HasPermission(ApplicationContext, Rules.AuthorizationActions.EditObject, this);
187 return (IsDirty && IsValid && auth && !IsBusy);
188 }
189 }
190
191#endregion
192
193#region Begin/Cancel/ApplyEdit
194
215 public void BeginEdit()
216 {
217 if (this.IsChild)
218 throw new NotSupportedException(Resources.NoBeginEditChildException);
219
220 CopyState(this.EditLevel + 1);
221 }
222
236 public void CancelEdit()
237 {
238 if (this.IsChild)
239 throw new NotSupportedException(Resources.NoCancelEditChildException);
240
241 UndoChanges(this.EditLevel - 1);
242 }
243
257 public void ApplyEdit()
258 {
259 if (this.IsChild)
260 throw new NotSupportedException(Resources.NoApplyEditChildException);
261
262 AcceptChanges(this.EditLevel - 1);
263 }
264
265 void Core.IParent.ApplyEditChild(Core.IEditableBusinessObject child)
266 {
267 EditChildComplete(child);
268 }
269
271 {
272 get { return this.Parent; }
273 }
280 protected virtual void EditChildComplete(Core.IEditableBusinessObject child)
281 {
282
283 // do nothing, we don't really care
284 // when a child has its edits applied
285 }
286
287#endregion
288
289#region N-level undo
290
291 void Core.IUndoableObject.CopyState(int parentEditLevel, bool parentBindingEdit)
292 {
293 if (!parentBindingEdit)
294 CopyState(parentEditLevel);
295 }
296
297 void Core.IUndoableObject.UndoChanges(int parentEditLevel, bool parentBindingEdit)
298 {
299 if (!parentBindingEdit)
300 UndoChanges(parentEditLevel);
301 }
302
303 void Core.IUndoableObject.AcceptChanges(int parentEditLevel, bool parentBindingEdit)
304 {
305 if (!parentBindingEdit)
306 AcceptChanges(parentEditLevel);
307 }
308
309 private void CopyState(int parentEditLevel)
310 {
311 if (this.EditLevel + 1 > parentEditLevel)
312 throw new UndoException(string.Format(Resources.EditLevelMismatchException, "CopyState"), this.GetType().Name, _parent != null ? _parent.GetType().Name : null, this.EditLevel, parentEditLevel - 1);
313
314 // we are going a level deeper in editing
315 _editLevel += 1;
316
317 // cascade the call to all child objects
318 foreach (C child in this)
319 child.CopyState(_editLevel, false);
320
321 // cascade the call to all deleted child objects
322 foreach (C child in DeletedList)
323 child.CopyState(_editLevel, false);
324 }
325
326 private bool _completelyRemoveChild;
327
328 private void UndoChanges(int parentEditLevel)
329 {
330 C child;
331
332 if (this.EditLevel - 1 != parentEditLevel)
333 throw new UndoException(string.Format(Resources.EditLevelMismatchException, "UndoChanges"), this.GetType().Name, _parent != null ? _parent.GetType().Name : null, this.EditLevel, parentEditLevel + 1);
334
335 // we are coming up one edit level
336 _editLevel -= 1;
337 if (_editLevel < 0) _editLevel = 0;
338
339 try
340 {
341 using (LoadListMode)
342 {
343 // Cancel edit on all current items
344 for (int index = Count - 1; index >= 0; index--)
345 {
346 child = this[index];
347
348 child.UndoChanges(_editLevel, false);
349
350 // if item is below its point of addition, remove
351 if (child.EditLevelAdded > _editLevel)
352 {
353 bool oldAllowRemove = this.AllowRemove;
354 try
355 {
356 this.AllowRemove = true;
357 _completelyRemoveChild = true;
358 RemoveAt(index);
359 }
360 finally
361 {
362 _completelyRemoveChild = false;
363 this.AllowRemove = oldAllowRemove;
364 }
365 }
366 }
367
368 // cancel edit on all deleted items
369 for (int index = DeletedList.Count - 1; index >= 0; index--)
370 {
371 child = DeletedList[index];
372 child.UndoChanges(_editLevel, false);
373 if (child.EditLevelAdded > _editLevel)
374 {
375 // if item is below its point of addition, remove
376 DeletedList.RemoveAt(index);
377 }
378 else
379 {
380 // if item is no longer deleted move back to main list
381 if (!child.IsDeleted) UnDeleteChild(child);
382 }
383 }
384 }
385 }
386 finally
387 {
388 OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
389 }
390 }
391
392 private void AcceptChanges(int parentEditLevel)
393 {
394 if (this.EditLevel - 1 != parentEditLevel)
395 throw new UndoException(string.Format(Resources.EditLevelMismatchException, "AcceptChanges"), this.GetType().Name, _parent != null ? _parent.GetType().Name : null, this.EditLevel, parentEditLevel + 1);
396
397 // we are coming up one edit level
398 _editLevel -= 1;
399 if (_editLevel < 0) _editLevel = 0;
400
401 // cascade the call to all child objects
402 foreach (C child in this)
403 {
404 child.AcceptChanges(_editLevel, false);
405 // if item is below its point of addition, lower point of addition
406 if (child.EditLevelAdded > _editLevel) child.EditLevelAdded = _editLevel;
407 }
408
409 // cascade the call to all deleted child objects
410 for (int index = DeletedList.Count - 1; index >= 0; index--)
411 {
412 C child = DeletedList[index];
413 child.AcceptChanges(_editLevel, false);
414 // if item is below its point of addition, remove
415 if (child.EditLevelAdded > _editLevel)
416 DeletedList.RemoveAt(index);
417 }
418 }
419
420#endregion
421
422#region Delete and Undelete child
423
424 private MobileList<C> _deletedList;
425
430 [System.Diagnostics.CodeAnalysis.SuppressMessage(
431 "Microsoft.Design", "CA1002:DoNotExposeGenericLists")]
432 [EditorBrowsable(EditorBrowsableState.Advanced)]
434 {
435 get
436 {
437 if (_deletedList == null)
438 _deletedList = (MobileList<C>)ApplicationContext.CreateGenericInstanceDI(typeof(MobileList<>), typeof(C));
439 return _deletedList;
440 }
441 }
442
443 [System.Diagnostics.CodeAnalysis.SuppressMessage(
444 "Microsoft.Design", "CA1002:DoNotExposeGenericLists")]
445 [EditorBrowsable(EditorBrowsableState.Advanced)]
446 IEnumerable<IEditableBusinessObject> IContainsDeletedList.DeletedList => (IEnumerable<IEditableBusinessObject>)DeletedList;
447
448 private void DeleteChild(C child)
449 {
450 // set child edit level
451 Core.UndoableBase.ResetChildEditLevel(child, this.EditLevel, false);
452 // mark the object as deleted
453 child.DeleteChild();
454 // and add it to the deleted collection for storage
455 DeletedList.Add(child);
456 }
457
458 private void UnDeleteChild(C child)
459 {
460 // since the object is no longer deleted, remove it from
461 // the deleted collection
462 DeletedList.Remove(child);
463
464 // we are inserting an _existing_ object so
465 // we need to preserve the object's editleveladded value
466 // because it will be changed by the normal add process
467 int saveLevel = child.EditLevelAdded;
468 Add(child);
469 child.EditLevelAdded = saveLevel;
470 }
471
477 [EditorBrowsable(EditorBrowsableState.Advanced)]
478 public bool ContainsDeleted(C item)
479 {
480 return DeletedList.Contains(item);
481 }
482
483#endregion
484
485#region Insert, Remove, Clear
486
491 protected override object AddNewCore()
492 {
494 var item = dp.CreateChild();
495 Add(item);
496 return item;
497 }
498
504 void Core.IEditableCollection.RemoveChild(Csla.Core.IEditableBusinessObject child)
505 {
506 Remove((C)child);
507 }
508
510 {
511 return DeletedList;
512 }
513
519 void Core.IParent.RemoveChild(Csla.Core.IEditableBusinessObject child)
520 {
521 Remove((C)child);
522 }
523
529 protected override void InsertItem(int index, C item)
530 {
531 // set parent reference
532 item.SetParent(this);
533 // set child edit level
534 Core.UndoableBase.ResetChildEditLevel(item, this.EditLevel, false);
535 // when an object is inserted we assume it is
536 // a new object and so the edit level when it was
537 // added must be set
538 item.EditLevelAdded = _editLevel;
539 base.InsertItem(index, item);
540 }
541
547 protected override void RemoveItem(int index)
548 {
549 // when an object is 'removed' it is really
550 // being deleted, so do the deletion work
551 C child = this[index];
552 using (LoadListMode)
553 {
554 base.RemoveItem(index);
555 }
556 if (!_completelyRemoveChild)
557 {
558 // the child shouldn't be completely removed,
559 // so copy it to the deleted list
560 DeleteChild(child);
561 }
562 if (RaiseListChangedEvents)
563 OnListChanged(new ListChangedEventArgs(ListChangedType.ItemDeleted, index));
564 }
565
570 protected override void ClearItems()
571 {
572 while (base.Count > 0)
573 RemoveItem(0);
574 base.ClearItems();
575 }
576
588 protected override void SetItem(int index, C item)
589 {
590 C child = default(C);
591 if (!(ReferenceEquals((C)(this[index]), item)))
592 child = this[index];
593 // replace the original object with this new
594 // object
595 using (LoadListMode)
596 {
597 // set parent reference
598 item.SetParent(this);
599 // set child edit level
600 Core.UndoableBase.ResetChildEditLevel(item, this.EditLevel, false);
601 // reset EditLevelAdded
602 item.EditLevelAdded = this.EditLevel;
603
604 // add to list
605 base.SetItem(index, item);
606 }
607 if (child != null)
608 DeleteChild(child);
609 if (RaiseListChangedEvents)
610 OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, index));
611 }
612
613#endregion
614
615#region Cascade child events
616
622 [EditorBrowsable(EditorBrowsableState.Never)]
623 protected override void Child_PropertyChanged(object sender, PropertyChangedEventArgs e)
624 {
625 if (_deserialized && RaiseListChangedEvents && e != null)
626 {
627 for (int index = 0; index < Count; index++)
628 {
629 if (ReferenceEquals(this[index], sender))
630 {
631 PropertyDescriptor descriptor = GetPropertyDescriptor(e.PropertyName);
632 if (descriptor != null)
633 OnListChanged(new ListChangedEventArgs(
634 ListChangedType.ItemChanged, index, descriptor));
635 else
636 OnListChanged(new ListChangedEventArgs(
637 ListChangedType.ItemChanged, index));
638 }
639 }
640 }
641 base.Child_PropertyChanged(sender, e);
642 }
643
644 private static PropertyDescriptorCollection _propertyDescriptors;
645
646 private PropertyDescriptor GetPropertyDescriptor(string propertyName)
647 {
648 if (_propertyDescriptors == null)
649 _propertyDescriptors = TypeDescriptor.GetProperties(typeof(C));
650 PropertyDescriptor result = null;
651 foreach (PropertyDescriptor desc in _propertyDescriptors)
652 if (desc.Name == propertyName)
653 {
654 result = desc;
655 break;
656 }
657 return result;
658 }
659
660#endregion
661
662#region Edit level tracking
663
664 // keep track of how many edit levels we have
665 private int _editLevel;
666
670 [EditorBrowsable(EditorBrowsableState.Never)]
671 protected int EditLevel
672 {
673 get { return _editLevel; }
674 }
675
676 int Core.IUndoableObject.EditLevel
677 {
678 get
679 {
680 return this.EditLevel;
681 }
682 }
683
684#endregion
685
686#region IsChild
687
688 [NotUndoable()]
689 private bool _isChild = false;
690
695 [Browsable(false)]
696 [System.ComponentModel.DataAnnotations.Display(AutoGenerateField = false)]
697 [System.ComponentModel.DataAnnotations.ScaffoldColumn(false)]
698 public bool IsChild
699 {
700 get { return _isChild; }
701 }
702
720 protected void MarkAsChild()
721 {
722 _identity = -1;
723 _isChild = true;
724 }
725
726#endregion
727
728#region ICloneable
729
730 object ICloneable.Clone()
731 {
732 return GetClone();
733 }
734
739 [EditorBrowsable(EditorBrowsableState.Advanced)]
740 protected virtual object GetClone()
741 {
742 return Core.ObjectCloner.GetInstance(ApplicationContext).Clone(this);
743 }
744
749 public T Clone()
750 {
751 return (T)GetClone();
752 }
753
754#endregion
755
756#region Serialization Notification
757
758 [NonSerialized]
759 [NotUndoable]
760 private bool _deserialized = false;
761
766 [EditorBrowsable(EditorBrowsableState.Advanced)]
767 protected override void OnDeserialized()
768 {
769 _deserialized = true;
770 base.OnDeserialized();
771
772 foreach (Core.IEditableBusinessObject child in this)
773 {
774 child.SetParent(this);
775 }
776
777 foreach (Core.IEditableBusinessObject child in DeletedList)
778 child.SetParent(this);
779 }
780
781#endregion
782
783#region Child Data Access
784
789 [EditorBrowsable(EditorBrowsableState.Advanced)]
790 protected virtual void Child_Create()
791 { /* do nothing - list self-initializes */ }
792
802 [EditorBrowsable(EditorBrowsableState.Advanced)]
803 protected virtual void Child_Update(params object[] parameters)
804 {
805 using (LoadListMode)
806 {
808 foreach (var child in DeletedList)
809 dp.UpdateChild(child, parameters);
810 DeletedList.Clear();
811
812 foreach (var child in this)
813 if (child.IsDirty) dp.UpdateChild(child, parameters);
814 }
815 }
816
817#endregion
818
819#region Data Access
820
848 public T Save()
849 {
850 try
851 {
852 return SaveAsync(null, true).Result;
853 }
854 catch (AggregateException ex)
855 {
856 if (ex.InnerExceptions.Count > 0)
857 throw ex.InnerExceptions[0];
858 else
859 throw;
860 }
861 }
862
866 public async Task<T> SaveAsync()
867 {
868 return await SaveAsync(null, false);
869 }
870
876 public async Task SaveAndMergeAsync()
877 {
878 new GraphMerger(ApplicationContext).MergeBusinessBindingListGraph<T, C>((T)this, await SaveAsync());
879 }
880
886 protected virtual async Task<T> SaveAsync(object userState, bool isSync)
887 {
888 T result;
889 if (this.IsChild)
890 throw new InvalidOperationException(Resources.NoSaveChildException);
891
892 if (_editLevel > 0)
893 throw new InvalidOperationException(Resources.NoSaveEditingException);
894
895 if (!IsValid)
896 throw new Rules.ValidationException(Resources.NoSaveInvalidException);
897
898 if (IsBusy)
899 throw new InvalidOperationException(Resources.BusyObjectsMayNotBeSaved);
900
901 if (IsDirty)
902 {
904 if (isSync)
905 {
906 result = dp.Update((T)this);
907 }
908 else
909 {
910 result = await dp.UpdateAsync((T)this);
911 }
912 }
913 else
914 {
915 result = (T)this;
916 }
917 OnSaved(result, null, userState);
918 return result;
919 }
920
926 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", MessageId = "Member")]
927 [EditorBrowsable(EditorBrowsableState.Advanced)]
929 {
930
931 }
932
938 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", MessageId = "Member")]
939 [EditorBrowsable(EditorBrowsableState.Advanced)]
941 {
942
943 }
944
951 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", MessageId = "Member")]
952 [EditorBrowsable(EditorBrowsableState.Advanced)]
953 protected virtual void DataPortal_OnDataPortalException(DataPortalEventArgs e, Exception ex)
954 {
955
956 }
957
963 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", MessageId = "Member")]
964 [EditorBrowsable(EditorBrowsableState.Advanced)]
966 {
967 }
968
974 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", MessageId = "Member")]
975 [EditorBrowsable(EditorBrowsableState.Advanced)]
977 {
978 }
979
986 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", MessageId = "Member")]
987 [EditorBrowsable(EditorBrowsableState.Advanced)]
988 protected virtual void Child_OnDataPortalException(DataPortalEventArgs e, Exception ex)
989 {
990 }
991
992#endregion
993
994#region ISavable Members
995
996 object Csla.Core.ISavable.Save()
997 {
998 return Save();
999 }
1000
1001 object Csla.Core.ISavable.Save(bool forceUpdate)
1002 {
1003 return Save();
1004 }
1005
1006 async Task<object> ISavable.SaveAsync()
1007 {
1008 return await SaveAsync();
1009 }
1010
1011 async Task<object> ISavable.SaveAsync(bool forceUpdate)
1012 {
1013 return await SaveAsync();
1014 }
1015
1016 async Task ISavable.SaveAndMergeAsync(bool forceUpdate)
1017 {
1018 await SaveAndMergeAsync();
1019 }
1020
1021 void Csla.Core.ISavable.SaveComplete(object newObject)
1022 {
1023 OnSaved((T)newObject, null, null);
1024 }
1025
1026 T Csla.Core.ISavable<T>.Save(bool forceUpdate)
1027 {
1028 return Save();
1029 }
1030
1031 async Task<T> ISavable<T>.SaveAsync(bool forceUpdate)
1032 {
1033 return await SaveAsync();
1034 }
1035
1036 async Task ISavable<T>.SaveAndMergeAsync(bool forceUpdate)
1037 {
1038 await SaveAndMergeAsync();
1039 }
1040
1041 void Csla.Core.ISavable<T>.SaveComplete(T newObject)
1042 {
1043 OnSaved(newObject, null, null);
1044 }
1045
1046 [NonSerialized()]
1047 [NotUndoable]
1048 private EventHandler<Csla.Core.SavedEventArgs> _nonSerializableSavedHandlers;
1049 [NotUndoable]
1050 private EventHandler<Csla.Core.SavedEventArgs> _serializableSavedHandlers;
1051
1055 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design",
1056 "CA1062:ValidateArgumentsOfPublicMethods")]
1057 public event EventHandler<Csla.Core.SavedEventArgs> Saved
1058 {
1059 add
1060 {
1061 if (value.Method.IsPublic &&
1062 (value.Method.DeclaringType.IsSerializable ||
1063 value.Method.IsStatic))
1064 _serializableSavedHandlers = (EventHandler<Csla.Core.SavedEventArgs>)
1065 System.Delegate.Combine(_serializableSavedHandlers, value);
1066 else
1067 _nonSerializableSavedHandlers = (EventHandler<Csla.Core.SavedEventArgs>)
1068 System.Delegate.Combine(_nonSerializableSavedHandlers, value);
1069 }
1070 remove
1071 {
1072 if (value.Method.IsPublic &&
1073 (value.Method.DeclaringType.IsSerializable ||
1074 value.Method.IsStatic))
1075 _serializableSavedHandlers = (EventHandler<Csla.Core.SavedEventArgs>)
1076 System.Delegate.Remove(_serializableSavedHandlers, value);
1077 else
1078 _nonSerializableSavedHandlers = (EventHandler<Csla.Core.SavedEventArgs>)
1079 System.Delegate.Remove(_nonSerializableSavedHandlers, value);
1080 }
1081 }
1082
1091 [System.ComponentModel.EditorBrowsable(EditorBrowsableState.Advanced)]
1092 protected virtual void OnSaved(T newObject, Exception e, object userState)
1093 {
1094 Csla.Core.SavedEventArgs args = new Csla.Core.SavedEventArgs(newObject, e, userState);
1095 if (_nonSerializableSavedHandlers != null)
1096 _nonSerializableSavedHandlers.Invoke(this, args);
1097 if (_serializableSavedHandlers != null)
1098 _serializableSavedHandlers.Invoke(this, args);
1099 }
1100
1101#endregion
1102
1103#region Parent/Child link
1104
1105 [NotUndoable(), NonSerialized()]
1106 private Core.IParent _parent;
1107
1115 [Browsable(false)]
1116 [System.ComponentModel.DataAnnotations.Display(AutoGenerateField = false)]
1117 [System.ComponentModel.DataAnnotations.ScaffoldColumn(false)]
1118 [EditorBrowsable(EditorBrowsableState.Advanced)]
1119 public Core.IParent Parent
1120 {
1121 get
1122 {
1123 return _parent;
1124 }
1125 }
1126
1133 protected virtual void SetParent(Core.IParent parent)
1134 {
1135 _parent = parent;
1136 _identityManager = null;
1137 InitializeIdentity();
1138 }
1139
1146 void Core.IEditableCollection.SetParent(Core.IParent parent)
1147 {
1148 this.SetParent(parent);
1149 }
1150
1151#endregion
1152
1153#region ToArray
1154
1158 public C[] ToArray()
1159 {
1160 List<C> result = new List<C>();
1161 foreach (C item in this)
1162 result.Add(item);
1163 return result.ToArray();
1164 }
1165#endregion
1166
1167#region ITrackStatus
1168
1169 bool Core.ITrackStatus.IsNew
1170 {
1171 get
1172 {
1173 return false;
1174 }
1175 }
1176
1177 bool Core.ITrackStatus.IsDeleted
1178 {
1179 get
1180 {
1181 return false;
1182 }
1183 }
1184
1188 [Browsable(false)]
1189 [System.ComponentModel.DataAnnotations.Display(AutoGenerateField = false)]
1190 [System.ComponentModel.DataAnnotations.ScaffoldColumn(false)]
1191 public override bool IsBusy
1192 {
1193 get
1194 {
1195 // any non-new deletions make us dirty
1196 foreach (C item in DeletedList)
1197 if (item.IsBusy)
1198 return true;
1199
1200 // run through all the child objects
1201 // and if any are dirty then then
1202 // collection is dirty
1203 foreach (C child in this)
1204 if (child.IsBusy)
1205 return true;
1206
1207 return false;
1208 }
1209 }
1210
1211#endregion
1212
1213#region IDataPortalTarget Members
1214
1215 void Csla.Server.IDataPortalTarget.CheckRules()
1216 { }
1217
1218 void Csla.Server.IDataPortalTarget.MarkAsChild()
1219 {
1220 this.MarkAsChild();
1221 }
1222
1223 void Csla.Server.IDataPortalTarget.MarkNew()
1224 { }
1225
1226 void Csla.Server.IDataPortalTarget.MarkOld()
1227 { }
1228
1229 void Csla.Server.IDataPortalTarget.DataPortal_OnDataPortalInvoke(DataPortalEventArgs e)
1230 {
1232 }
1233
1234 void Csla.Server.IDataPortalTarget.DataPortal_OnDataPortalInvokeComplete(DataPortalEventArgs e)
1235 {
1237 }
1238
1239 void Csla.Server.IDataPortalTarget.DataPortal_OnDataPortalException(DataPortalEventArgs e, Exception ex)
1240 {
1242 }
1243
1244 void Csla.Server.IDataPortalTarget.Child_OnDataPortalInvoke(DataPortalEventArgs e)
1245 {
1247 }
1248
1249 void Csla.Server.IDataPortalTarget.Child_OnDataPortalInvokeComplete(DataPortalEventArgs e)
1250 {
1252 }
1253
1254 void Csla.Server.IDataPortalTarget.Child_OnDataPortalException(DataPortalEventArgs e, Exception ex)
1255 {
1256 this.Child_OnDataPortalException(e, ex);
1257 }
1258
1259#endregion
1260
1261#region Mobile object overrides
1262
1270 [System.ComponentModel.EditorBrowsable(EditorBrowsableState.Advanced)]
1272 {
1273 _isChild = info.GetValue<bool>("Csla.BusinessListBase._isChild");
1274 _editLevel = info.GetValue<int>("Csla.BusinessListBase._editLevel");
1275 _identity = info.GetValue<int>("Csla.Core.BusinessBase._identity");
1276 base.OnSetState(info);
1277 }
1278
1286 [System.ComponentModel.EditorBrowsable(EditorBrowsableState.Advanced)]
1288 {
1289 info.AddValue("Csla.BusinessListBase._isChild", _isChild);
1290 info.AddValue("Csla.BusinessListBase._editLevel", _editLevel);
1291 info.AddValue("Csla.Core.BusinessBase._identity", _identity);
1292 base.OnGetState(info);
1293 }
1294
1305 [System.ComponentModel.EditorBrowsable(EditorBrowsableState.Advanced)]
1307 {
1308 base.OnGetChildren(info, formatter);
1309 if (_deletedList != null)
1310 {
1311 var fieldManagerInfo = formatter.SerializeObject(_deletedList);
1312 info.AddChild("_deletedList", fieldManagerInfo.ReferenceId);
1313 }
1314 }
1315
1326 [System.ComponentModel.EditorBrowsable(EditorBrowsableState.Advanced)]
1328 {
1329 if (info.Children.ContainsKey("_deletedList"))
1330 {
1331 var childData = info.Children["_deletedList"];
1332 _deletedList = (MobileList<C>)formatter.GetObject(childData.ReferenceId);
1333 }
1334 base.OnSetChildren(info, formatter);
1335 }
1336
1337#endregion
1338 }
1339}
Provides consistent context information between the client and server DataPortal objects.
object CreateInstanceDI(Type objectType, params object[] parameters)
Creates an object using 'Activator.CreateInstance' using service provider (if one is available) to po...
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.
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.
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.
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.
async Task SaveAndMergeAsync()
Saves the object to the database, merging any resulting updates into the existing object graph.
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.
ApplicationContext ApplicationContext
Gets the current ApplicationContext
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 type.
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.
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.
Implements behavior to merge one object graph into a clone of itself (typically post-serialization).
Definition: GraphMerger.cs:20
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.
Client side data portal used for making asynchronous data portal calls in .NET.
Definition: DataPortalT.cs:24
T CreateChild()
Creates and initializes a new child business object.
Definition: DataPortalT.cs:639
void UpdateChild(T child)
Inserts, updates or deletes an existing child business object.
Definition: DataPortalT.cs:734
T Update(T obj)
Called by a factory method in a business class or by the UI to update an object.
Definition: DataPortalT.cs:467
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(ApplicationContext applicationContext, 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.
Implement if a class requires access to the CSLA ApplicationContext type.
ApplicationContext ApplicationContext
Gets or sets the current ApplicationContext object.
Defines an object that holds a list of deleted items.
IEnumerable< IEditableBusinessObject > DeletedList
List of deleted child objects
@ Serializable
Prevents updating or inserting until the transaction is complete.