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.
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,
48 {
53 {
54 InitializeIdentity();
55 Initialize();
56 AllowNew = true;
57 }
58
59#region Initialize
60
66 protected virtual void Initialize()
67 { /* allows subclass to initialize events before any other activity occurs */ }
68
69 #endregion
70
71 #region Identity
72
73 private int _identity = -1;
74
76 {
77 get { return _identity; }
78 }
79
80 private void InitializeIdentity()
81 {
82 _identity = ((IParent)this).GetNextIdentity(_identity);
83 }
84
85 [NonSerialized]
86 [NotUndoable]
87 private IdentityManager _identityManager;
88
89 int IParent.GetNextIdentity(int current)
90 {
91 var me = (IParent)this;
92 if (me.Parent != null)
93 {
94 return me.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 SaveItem Methods
107
108 private bool _activelySaving;
109
122 public T SaveItem(T item)
123 {
124 return SaveItem(IndexOf(item));
125 }
126
139 public virtual T SaveItem(int index)
140 {
141 bool raisingEvents = this.RaiseListChangedEvents;
142 this.RaiseListChangedEvents = false;
143 _activelySaving = true;
144
145 T item = default(T);
146 T result = default(T);
147 try
148 {
149 item = this[index];
150 result = item;
151 T savable = item;
152
153 // clone the object if possible
154 ICloneable clonable = savable as ICloneable;
155 if (clonable != null)
156 savable = (T)clonable.Clone();
157
158 // commit all changes
159 int editLevel = savable.EditLevel;
160 for (int tmp = 1; tmp <= editLevel; tmp++)
161 savable.AcceptChanges(editLevel - tmp, false);
162
163 // do the save
164 result = (T)savable.Save();
165
166 if (!ReferenceEquals(result, item))
167 {
168 // restore edit level to previous level
169 for (int tmp = 1; tmp <= editLevel; tmp++)
170 result.CopyState(tmp, false);
171
172 // put result into collection
173 this[index] = result;
174 }
175
176 if (!ReferenceEquals(savable, item))
177 {
178 // raise Saved event from original object
179 Core.ISavable original = item as Core.ISavable;
180 if (original != null)
181 original.SaveComplete(result);
182 }
183
184 OnSaved(result, null);
185 }
186 finally
187 {
188 _activelySaving = false;
189 this.RaiseListChangedEvents = raisingEvents;
190 }
191 this.OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, index));
192 return result;
193 }
194
195#endregion
196
197#region Saved Event
198 [NonSerialized]
199 [NotUndoable]
200 private EventHandler<Csla.Core.SavedEventArgs> _nonSerializableSavedHandlers;
201 [NotUndoable]
202 private EventHandler<Csla.Core.SavedEventArgs> _serializableSavedHandlers;
203
207 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design",
208 "CA1062:ValidateArgumentsOfPublicMethods")]
209 public event EventHandler<Csla.Core.SavedEventArgs> Saved
210 {
211 add
212 {
213 if (value.Method.IsPublic &&
214 (value.Method.DeclaringType.IsSerializable ||
215 value.Method.IsStatic))
216 _serializableSavedHandlers = (EventHandler<Csla.Core.SavedEventArgs>)
217 System.Delegate.Combine(_serializableSavedHandlers, value);
218 else
219 _nonSerializableSavedHandlers = (EventHandler<Csla.Core.SavedEventArgs>)
220 System.Delegate.Combine(_nonSerializableSavedHandlers, value);
221 }
222 remove
223 {
224 if (value.Method.IsPublic &&
225 (value.Method.DeclaringType.IsSerializable ||
226 value.Method.IsStatic))
227 _serializableSavedHandlers = (EventHandler<Csla.Core.SavedEventArgs>)
228 System.Delegate.Remove(_serializableSavedHandlers, value);
229 else
230 _nonSerializableSavedHandlers = (EventHandler<Csla.Core.SavedEventArgs>)
231 System.Delegate.Remove(_nonSerializableSavedHandlers, value);
232 }
233 }
234
245 [EditorBrowsable(EditorBrowsableState.Advanced)]
246 protected virtual void OnSaved(T newObject, Exception e)
247 {
248 Csla.Core.SavedEventArgs args = new Csla.Core.SavedEventArgs(newObject, e, null);
249 if (_nonSerializableSavedHandlers != null)
250 _nonSerializableSavedHandlers.Invoke(this, args);
251 if (_serializableSavedHandlers != null)
252 _serializableSavedHandlers.Invoke(this, args);
253 }
254
255#endregion
256
257#region Insert, Remove, Clear
258
263 protected override object AddNewCore()
264 {
265 T item = Csla.DataPortal.Create<T>();
266 Add(item);
267 this.OnAddingNew(new AddingNewEventArgs(item));
268 return item;
269 }
270
277 protected override void InsertItem(int index, T item)
278 {
279 item.SetParent(this);
280 base.InsertItem(index, item);
281 }
282
288 protected override void RemoveItem(int index)
289 {
290 // delete item from database
291 T item = this[index];
292
293 // only delete/save the item if it is not new
294 bool raiseEventForNewItem = false;
295 if (!item.IsNew)
296 {
297 item.Delete();
298 SaveItem(index);
299 }
300 else
301 {
302 raiseEventForNewItem = true;
303 }
304
305 base.RemoveItem(index);
306 if (raiseEventForNewItem)
307 OnSaved(item, null);
308 }
309
316 protected override void SetItem(int index, T item)
317 {
318 item.SetParent(this);
319 base.SetItem(index, item);
320 }
321
322#endregion
323
324#region IParent Members
325
326 void Csla.Core.IParent.ApplyEditChild(Core.IEditableBusinessObject child)
327 {
328 if (!_activelySaving && child.EditLevel == 0)
329 SaveItem((T)child);
330 }
331
332 void Csla.Core.IParent.RemoveChild(Core.IEditableBusinessObject child)
333 {
334 if (child.IsNew)
335 Remove((T)child);
336 }
337
339 {
340 get { return null; }
341 }
342
343#endregion
344
345#region Cascade Child events
346
354 [EditorBrowsable(EditorBrowsableState.Never)]
355 protected override void Child_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
356 {
357 for (int index = 0; index < this.Count; index++)
358 {
359 if (ReferenceEquals(this[index], sender))
360 {
361 PropertyDescriptor descriptor = GetPropertyDescriptor(e.PropertyName);
362 if (descriptor != null)
363 OnListChanged(new ListChangedEventArgs(
364 ListChangedType.ItemChanged, index, GetPropertyDescriptor(e.PropertyName)));
365 else
366 OnListChanged(new ListChangedEventArgs(
367 ListChangedType.ItemChanged, index));
368 return;
369 }
370 }
371 OnChildPropertyChanged(sender, e);
372 base.Child_PropertyChanged(sender, e);
373 }
374
375 void Child_BusyChanged(object sender, BusyChangedEventArgs e)
376 {
377 OnBusyChanged(e);
378 }
379
390 [EditorBrowsable(EditorBrowsableState.Advanced)]
391 protected virtual void OnChildPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
392 { }
393
394 private static PropertyDescriptorCollection _propertyDescriptors;
395
396 private PropertyDescriptor GetPropertyDescriptor(string propertyName)
397 {
398 if (_propertyDescriptors == null)
399 _propertyDescriptors = TypeDescriptor.GetProperties(this.GetType());
400 PropertyDescriptor result = null;
401 foreach (PropertyDescriptor desc in _propertyDescriptors)
402 if (desc.Name == propertyName)
403 {
404 result = desc;
405 break;
406 }
407 return result;
408 }
409
410#endregion
411
412#region Serialization Notification
413
418 [EditorBrowsable(EditorBrowsableState.Advanced)]
419 protected override void OnDeserialized()
420 {
421 foreach (IEditableBusinessObject child in this)
422 {
423 child.SetParent(this);
424 INotifyPropertyChanged c = child as INotifyPropertyChanged;
425 if (c != null)
426 c.PropertyChanged += new PropertyChangedEventHandler(Child_PropertyChanged);
427 }
428 base.OnDeserialized();
429 }
430
431#endregion
432
433#region Data Access
434
435 private void DataPortal_Update()
436 {
437 throw new NotSupportedException(Properties.Resources.UpdateNotSupportedException);
438 }
439
440 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "criteria")]
441 [Delete]
442 private void DataPortal_Delete(object criteria)
443 {
444 throw new NotSupportedException(Properties.Resources.DeleteNotSupportedException);
445 }
446
452 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", MessageId = "Member"), EditorBrowsable(EditorBrowsableState.Advanced)]
454 {
455
456 }
457
463 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", MessageId = "Member"), EditorBrowsable(EditorBrowsableState.Advanced)]
465 {
466
467 }
468
475 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", MessageId = "Member"), EditorBrowsable(EditorBrowsableState.Advanced)]
476 protected virtual void DataPortal_OnDataPortalException(DataPortalEventArgs e, Exception ex)
477 {
478
479 }
480
481#endregion
482
483#region ToArray
484
488 public T[] ToArray()
489 {
490 List<T> result = new List<T>();
491 foreach (T item in this)
492 result.Add(item);
493 return result.ToArray();
494 }
495
496#endregion
497
498#region IDataPortalTarget Members
499
500 void Csla.Server.IDataPortalTarget.CheckRules()
501 { }
502
503 void Csla.Server.IDataPortalTarget.MarkAsChild()
504 { }
505
506 void Csla.Server.IDataPortalTarget.MarkNew()
507 { }
508
509 void Csla.Server.IDataPortalTarget.MarkOld()
510 { }
511
512 void Csla.Server.IDataPortalTarget.DataPortal_OnDataPortalInvoke(DataPortalEventArgs e)
513 {
515 }
516
517 void Csla.Server.IDataPortalTarget.DataPortal_OnDataPortalInvokeComplete(DataPortalEventArgs e)
518 {
520 }
521
522 void Csla.Server.IDataPortalTarget.DataPortal_OnDataPortalException(DataPortalEventArgs e, Exception ex)
523 {
525 }
526
527 void Csla.Server.IDataPortalTarget.Child_OnDataPortalInvoke(DataPortalEventArgs e)
528 { }
529
530 void Csla.Server.IDataPortalTarget.Child_OnDataPortalInvokeComplete(DataPortalEventArgs e)
531 { }
532
533 void Csla.Server.IDataPortalTarget.Child_OnDataPortalException(DataPortalEventArgs e, Exception ex)
534 { }
535
536#endregion
537
538#region IsBusy
539
544 public override bool IsBusy
545 {
546 get
547 {
548 // run through all the child objects
549 // and if any are dirty then then
550 // collection is dirty
551 foreach (T child in this)
552 if (child.IsBusy)
553 return true;
554
555 return false;
556 }
557 }
558
559 #endregion
560
561 #region Mobile object overrides
562
570 protected override void OnGetState(SerializationInfo info)
571 {
572 info.AddValue("Csla.Core.BusinessBase._identity", _identity);
573 base.OnGetState(info);
574 }
575
583 protected override void OnSetState(SerializationInfo info)
584 {
585 _identity = info.GetValue<int>("Csla.Core.BusinessBase._identity");
586 base.OnSetState(info);
587 }
588
589 #endregion
590 }
591}
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.
This is the client-side DataPortal.
Definition: DataPortalT.cs:24
static object Create(Type objectType, object criteria)
Called by a factory method in a business class to create a new object, which is loaded with default v...
Definition: DataPortal.cs:91
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 object.
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.
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.
Interface to be implemented by any object that supports serialization by the SerializationFormatterFa...
@ Serializable
Prevents updating or inserting until the transaction is complete.