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.
DynamicBindingListBase.cs
Go to the documentation of this file.
1//-----------------------------------------------------------------------
2// <copyright file="DynamicBindingListBase.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 collections</summary>
7//-----------------------------------------------------------------------
8using System;
9using System.Collections.Generic;
10using System.ComponentModel;
11using Csla.Core;
13
14namespace Csla
15{
41 [Serializable()]
42 public abstract class DynamicBindingListBase<T> :
43 Core.ExtendedBindingList<T>,
44 Core.IParent,
45 Server.IDataPortalTarget,
49 {
54 { }
55
59 protected ApplicationContext ApplicationContext { get; private set; }
60 ApplicationContext Core.IUseApplicationContext.ApplicationContext
61 {
62 get => ApplicationContext;
63 set
64 {
65 ApplicationContext = value;
66 InitializeIdentity();
67 Initialize();
68 AllowNew = true;
69 }
70 }
71
72 #region Initialize
73
79 protected virtual void Initialize()
80 { /* allows subclass to initialize events before any other activity occurs */ }
81
82 #endregion
83
84 #region Identity
85
86 private int _identity = -1;
87
89 {
90 get { return _identity; }
91 }
92
93 private void InitializeIdentity()
94 {
95 _identity = ((IParent)this).GetNextIdentity(_identity);
96 }
97
98 [NonSerialized]
99 [NotUndoable]
100 private IdentityManager _identityManager;
101
102 int IParent.GetNextIdentity(int current)
103 {
104 var me = (IParent)this;
105 if (me.Parent != null)
106 {
107 return me.Parent.GetNextIdentity(current);
108 }
109 else
110 {
111 if (_identityManager == null)
112 _identityManager = new IdentityManager();
113 return _identityManager.GetNextIdentity(current);
114 }
115 }
116
117 #endregion
118
119 #region SaveItem Methods
120
121 private bool _activelySaving;
122
135 public T SaveItem(T item)
136 {
137 return SaveItem(IndexOf(item));
138 }
139
152 public virtual T SaveItem(int index)
153 {
154 bool raisingEvents = this.RaiseListChangedEvents;
155 this.RaiseListChangedEvents = false;
156 _activelySaving = true;
157
158 T item = default(T);
159 T result = default(T);
160 try
161 {
162 item = this[index];
163 result = item;
164 T savable = item;
165
166 // clone the object if possible
167 ICloneable clonable = savable as ICloneable;
168 if (clonable != null)
169 savable = (T)clonable.Clone();
170
171 // commit all changes
172 int editLevel = savable.EditLevel;
173 for (int tmp = 1; tmp <= editLevel; tmp++)
174 savable.AcceptChanges(editLevel - tmp, false);
175
176 // do the save
177 result = (T)savable.Save();
178
179 if (!ReferenceEquals(result, item))
180 {
181 // restore edit level to previous level
182 for (int tmp = 1; tmp <= editLevel; tmp++)
183 result.CopyState(tmp, false);
184
185 // put result into collection
186 this[index] = result;
187 }
188
189 if (!ReferenceEquals(savable, item))
190 {
191 // raise Saved event from original object
192 Core.ISavable original = item as Core.ISavable;
193 if (original != null)
194 original.SaveComplete(result);
195 }
196
197 OnSaved(result, null);
198 }
199 finally
200 {
201 _activelySaving = false;
202 this.RaiseListChangedEvents = raisingEvents;
203 }
204 this.OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, index));
205 return result;
206 }
207
208#endregion
209
210#region Saved Event
211 [NonSerialized]
212 [NotUndoable]
213 private EventHandler<Csla.Core.SavedEventArgs> _nonSerializableSavedHandlers;
214 [NotUndoable]
215 private EventHandler<Csla.Core.SavedEventArgs> _serializableSavedHandlers;
216
220 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design",
221 "CA1062:ValidateArgumentsOfPublicMethods")]
222 public event EventHandler<Csla.Core.SavedEventArgs> Saved
223 {
224 add
225 {
226 if (value.Method.IsPublic &&
227 (value.Method.DeclaringType.IsSerializable ||
228 value.Method.IsStatic))
229 _serializableSavedHandlers = (EventHandler<Csla.Core.SavedEventArgs>)
230 System.Delegate.Combine(_serializableSavedHandlers, value);
231 else
232 _nonSerializableSavedHandlers = (EventHandler<Csla.Core.SavedEventArgs>)
233 System.Delegate.Combine(_nonSerializableSavedHandlers, value);
234 }
235 remove
236 {
237 if (value.Method.IsPublic &&
238 (value.Method.DeclaringType.IsSerializable ||
239 value.Method.IsStatic))
240 _serializableSavedHandlers = (EventHandler<Csla.Core.SavedEventArgs>)
241 System.Delegate.Remove(_serializableSavedHandlers, value);
242 else
243 _nonSerializableSavedHandlers = (EventHandler<Csla.Core.SavedEventArgs>)
244 System.Delegate.Remove(_nonSerializableSavedHandlers, value);
245 }
246 }
247
258 [EditorBrowsable(EditorBrowsableState.Advanced)]
259 protected virtual void OnSaved(T newObject, Exception e)
260 {
261 Csla.Core.SavedEventArgs args = new Csla.Core.SavedEventArgs(newObject, e, null);
262 if (_nonSerializableSavedHandlers != null)
263 _nonSerializableSavedHandlers.Invoke(this, args);
264 if (_serializableSavedHandlers != null)
265 _serializableSavedHandlers.Invoke(this, args);
266 }
267
268#endregion
269
270#region Insert, Remove, Clear
271
276 protected override object AddNewCore()
277 {
279 T item = dp.Create();
280 Add(item);
281 this.OnAddingNew(new AddingNewEventArgs(item));
282 return item;
283 }
284
291 protected override void InsertItem(int index, T item)
292 {
293 item.SetParent(this);
294 base.InsertItem(index, item);
295 }
296
302 protected override void RemoveItem(int index)
303 {
304 // delete item from database
305 T item = this[index];
306
307 // only delete/save the item if it is not new
308 bool raiseEventForNewItem = false;
309 if (!item.IsNew)
310 {
311 item.Delete();
312 SaveItem(index);
313 }
314 else
315 {
316 raiseEventForNewItem = true;
317 }
318
319 base.RemoveItem(index);
320 if (raiseEventForNewItem)
321 OnSaved(item, null);
322 }
323
330 protected override void SetItem(int index, T item)
331 {
332 item.SetParent(this);
333 base.SetItem(index, item);
334 }
335
336#endregion
337
338#region IParent Members
339
340 void Csla.Core.IParent.ApplyEditChild(Core.IEditableBusinessObject child)
341 {
342 if (!_activelySaving && child.EditLevel == 0)
343 SaveItem((T)child);
344 }
345
346 void Csla.Core.IParent.RemoveChild(Core.IEditableBusinessObject child)
347 {
348 if (child.IsNew)
349 Remove((T)child);
350 }
351
353 {
354 get { return null; }
355 }
356
357#endregion
358
359#region Cascade Child events
360
368 [EditorBrowsable(EditorBrowsableState.Never)]
369 protected override void Child_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
370 {
371 for (int index = 0; index < this.Count; index++)
372 {
373 if (ReferenceEquals(this[index], sender))
374 {
375 PropertyDescriptor descriptor = GetPropertyDescriptor(e.PropertyName);
376 if (descriptor != null)
377 OnListChanged(new ListChangedEventArgs(
378 ListChangedType.ItemChanged, index, GetPropertyDescriptor(e.PropertyName)));
379 else
380 OnListChanged(new ListChangedEventArgs(
381 ListChangedType.ItemChanged, index));
382 return;
383 }
384 }
385 OnChildPropertyChanged(sender, e);
386 base.Child_PropertyChanged(sender, e);
387 }
388
389 void Child_BusyChanged(object sender, BusyChangedEventArgs e)
390 {
391 OnBusyChanged(e);
392 }
393
404 [EditorBrowsable(EditorBrowsableState.Advanced)]
405 protected virtual void OnChildPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
406 { }
407
408 private static PropertyDescriptorCollection _propertyDescriptors;
409
410 private PropertyDescriptor GetPropertyDescriptor(string propertyName)
411 {
412 if (_propertyDescriptors == null)
413 _propertyDescriptors = TypeDescriptor.GetProperties(this.GetType());
414 PropertyDescriptor result = null;
415 foreach (PropertyDescriptor desc in _propertyDescriptors)
416 if (desc.Name == propertyName)
417 {
418 result = desc;
419 break;
420 }
421 return result;
422 }
423
424#endregion
425
426#region Serialization Notification
427
432 [EditorBrowsable(EditorBrowsableState.Advanced)]
433 protected override void OnDeserialized()
434 {
435 foreach (IEditableBusinessObject child in this)
436 {
437 child.SetParent(this);
438 INotifyPropertyChanged c = child as INotifyPropertyChanged;
439 if (c != null)
440 c.PropertyChanged += new PropertyChangedEventHandler(Child_PropertyChanged);
441 }
442 base.OnDeserialized();
443 }
444
445#endregion
446
447#region Data Access
448
449 private void DataPortal_Update()
450 {
451 throw new NotSupportedException(Properties.Resources.UpdateNotSupportedException);
452 }
453
454 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "criteria")]
455 [Delete]
456 private void DataPortal_Delete(object criteria)
457 {
458 throw new NotSupportedException(Properties.Resources.DeleteNotSupportedException);
459 }
460
466 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", MessageId = "Member"), EditorBrowsable(EditorBrowsableState.Advanced)]
468 {
469
470 }
471
477 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", MessageId = "Member"), EditorBrowsable(EditorBrowsableState.Advanced)]
479 {
480
481 }
482
489 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", MessageId = "Member"), EditorBrowsable(EditorBrowsableState.Advanced)]
490 protected virtual void DataPortal_OnDataPortalException(DataPortalEventArgs e, Exception ex)
491 {
492
493 }
494
495#endregion
496
497#region ToArray
498
502 public T[] ToArray()
503 {
504 List<T> result = new List<T>();
505 foreach (T item in this)
506 result.Add(item);
507 return result.ToArray();
508 }
509
510#endregion
511
512#region IDataPortalTarget Members
513
514 void Csla.Server.IDataPortalTarget.CheckRules()
515 { }
516
517 void Csla.Server.IDataPortalTarget.MarkAsChild()
518 { }
519
520 void Csla.Server.IDataPortalTarget.MarkNew()
521 { }
522
523 void Csla.Server.IDataPortalTarget.MarkOld()
524 { }
525
526 void Csla.Server.IDataPortalTarget.DataPortal_OnDataPortalInvoke(DataPortalEventArgs e)
527 {
529 }
530
531 void Csla.Server.IDataPortalTarget.DataPortal_OnDataPortalInvokeComplete(DataPortalEventArgs e)
532 {
534 }
535
536 void Csla.Server.IDataPortalTarget.DataPortal_OnDataPortalException(DataPortalEventArgs e, Exception ex)
537 {
539 }
540
541 void Csla.Server.IDataPortalTarget.Child_OnDataPortalInvoke(DataPortalEventArgs e)
542 { }
543
544 void Csla.Server.IDataPortalTarget.Child_OnDataPortalInvokeComplete(DataPortalEventArgs e)
545 { }
546
547 void Csla.Server.IDataPortalTarget.Child_OnDataPortalException(DataPortalEventArgs e, Exception ex)
548 { }
549
550#endregion
551
552#region IsBusy
553
558 public override bool IsBusy
559 {
560 get
561 {
562 // run through all the child objects
563 // and if any are dirty then then
564 // collection is dirty
565 foreach (T child in this)
566 if (child.IsBusy)
567 return true;
568
569 return false;
570 }
571 }
572
573 #endregion
574
575 #region Mobile object overrides
576
584 protected override void OnGetState(SerializationInfo info)
585 {
586 info.AddValue("Csla.Core.BusinessBase._identity", _identity);
587 base.OnGetState(info);
588 }
589
597 protected override void OnSetState(SerializationInfo info)
598 {
599 _identity = info.GetValue<int>("Csla.Core.BusinessBase._identity");
600 base.OnSetState(info);
601 }
602
603 #endregion
604 }
605}
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...
ApplicationContext(ApplicationContextAccessor applicationContextAccessor)
Creates a new instance of the type
Event arguments for the BusyChanged event.
Extends BindingList of T by adding extra behaviors.
virtual void OnBusyChanged(BusyChangedEventArgs args)
Override this method to be notified when the IsBusy property has changed.
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...
Event arguments containing a reference to the new object that was returned as a result of the Save() ...
Provides information about the DataPortal call.
Client side data portal used for making asynchronous data portal calls in .NET.
Definition: DataPortalT.cs:24
T Create(params object[] criteria)
Called by a factory method in a business class to create a new object, which is loaded with default v...
Definition: DataPortalT.cs:151
This is the base class from which collections of editable root business objects should be derived.
EventHandler< Csla.Core.SavedEventArgs > Saved
Event raised when an object has been saved.
override void Child_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
Handles any PropertyChanged event from a child object and echoes it up as a ChildChanged event.
virtual void OnChildPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
Override this method to be notified when a child object has been changed.
override bool IsBusy
Gets a value indicating whether this object is currently running an async operation.
virtual void DataPortal_OnDataPortalInvokeComplete(DataPortalEventArgs e)
Called by the server-side DataPortal after calling the requested DataPortal_xyz method.
virtual void OnSaved(T newObject, Exception e)
Raises the Saved event.
virtual void DataPortal_OnDataPortalException(DataPortalEventArgs e, Exception ex)
Called by the server-side DataPortal if an exception occurs during data access.
T[] ToArray()
Get an array containing all items in the list.
virtual void Initialize()
Override this method to set up event handlers so user code in a partial class can respond to events r...
virtual void DataPortal_OnDataPortalInvoke(DataPortalEventArgs e)
Called by the server-side DataPortal prior to calling the requested DataPortal_xyz method.
override void OnSetState(SerializationInfo info)
Override this method to retrieve your field values from the MobileFormatter serialzation stream.
override void OnGetState(SerializationInfo info)
Override this method to insert your field values into the MobileFormatter serialzation stream.
DynamicBindingListBase()
Creates an instance of the type.
override void SetItem(int index, T item)
Replaces item in the list.
override void InsertItem(int index, T item)
Gives the new object a parent reference to this list.
override void OnDeserialized()
This method is called on a newly deserialized object after deserialization is complete.
T SaveItem(T item)
Saves the specified item in the list.
ApplicationContext ApplicationContext
Gets the current ApplicationContext
override object AddNewCore()
Adds a new item to the list.
override void RemoveItem(int index)
Removes an item from the list.
virtual T SaveItem(int index)
Saves the specified item in the list.
Object containing the serialization data for a specific object.
void AddValue(string name, object value)
Adds a value to the serialization stream.
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.
void SetParent(IParent parent)
Used by BusinessListBase as a child object is created to tell the child object about its parent.
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...
void ApplyEditChild(Core.IEditableBusinessObject child)
Override this method to be notified when a child object's Core.BusinessBase.ApplyEdit method has comp...
void RemoveChild(Core.IEditableBusinessObject child)
This method is called by a child object when it wants to be removed from the collection.
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
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.
Interface to be implemented by any object that supports serialization by the SerializationFormatterFa...
@ Serializable
Prevents updating or inserting until the transaction is complete.