282 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			282 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System;
 | |
| using System.Collections.Generic;
 | |
| using System.Text;
 | |
| using System.Runtime.Serialization;
 | |
| using System.ComponentModel;
 | |
| 
 | |
| namespace Csla
 | |
| {
 | |
|   /// <summary>
 | |
|   /// This is the base class from which collections
 | |
|   /// of editable root business objects should be
 | |
|   /// derived.
 | |
|   /// </summary>
 | |
|   /// <typeparam name="T">
 | |
|   /// Type of editable root object to contain within
 | |
|   /// the collection.
 | |
|   /// </typeparam>
 | |
|   /// <remarks>
 | |
|   /// <para>
 | |
|   /// Your subclass should implement a factory method
 | |
|   /// and should override or overload
 | |
|   /// DataPortal_Fetch() to implement data retrieval.
 | |
|   /// </para><para>
 | |
|   /// Saving (inserts or updates) of items in the collection
 | |
|   /// should be handled through the SaveItem() method on
 | |
|   /// the collection. 
 | |
|   /// </para><para>
 | |
|   /// Removing an item from the collection
 | |
|   /// through Remove() or RemoveAt() causes immediate deletion
 | |
|   /// of the object, by calling the object's Delete() and
 | |
|   /// Save() methods.
 | |
|   /// </para>
 | |
|   /// </remarks>
 | |
|   [Serializable()]
 | |
|   public abstract class EditableRootListBase<T> : Core.ExtendedBindingList<T>, Core.IParent
 | |
|     where T : Core.IEditableBusinessObject, Core.ISavable
 | |
|   {
 | |
| 
 | |
|     #region  SaveItem Methods
 | |
| 
 | |
|     private bool _activelySaving;
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Saves the specified item in the list.
 | |
|     /// </summary>
 | |
|     /// <param name="item">
 | |
|     /// Reference to the item to be saved.
 | |
|     /// </param>
 | |
|     /// <remarks>
 | |
|     /// This method properly saves the child item,
 | |
|     /// by making sure the item in the collection
 | |
|     /// is properly replaced by the result of the
 | |
|     /// Save() method call.
 | |
|     /// </remarks>
 | |
|     public void SaveItem(T item)
 | |
|     {
 | |
| 
 | |
|       SaveItem(IndexOf(item));
 | |
| 
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Saves the specified item in the list.
 | |
|     /// </summary>
 | |
|     /// <param name="index">
 | |
|     /// Index of the item to be saved.
 | |
|     /// </param>
 | |
|     /// <remarks>
 | |
|     /// This method properly saves the child item,
 | |
|     /// by making sure the item in the collection
 | |
|     /// is properly replaced by the result of the
 | |
|     /// Save() method call.
 | |
|     /// </remarks>
 | |
|     public virtual void SaveItem(int index)
 | |
|     {
 | |
|       bool raisingEvents = this.RaiseListChangedEvents;
 | |
|       this.RaiseListChangedEvents = false;
 | |
| 
 | |
|       _activelySaving = true;
 | |
| 
 | |
|       T item = this[index];
 | |
|       int editLevel = item.EditLevel;
 | |
|       // commit all changes
 | |
|       for (int tmp = 1; tmp <= editLevel; tmp++)
 | |
|         item.AcceptChanges();
 | |
|       try
 | |
|       {
 | |
|         // do the save
 | |
|         this[index] = (T)item.Save();
 | |
|       }
 | |
|       finally
 | |
|       {
 | |
|         // restore edit level to previous level
 | |
|         for (int tmp = 1; tmp <= editLevel; tmp++)
 | |
|           item.CopyState();
 | |
|         _activelySaving = false;
 | |
|         this.RaiseListChangedEvents = raisingEvents;
 | |
|       }
 | |
|       this.OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, index));
 | |
|     }
 | |
| 
 | |
|     #endregion
 | |
| 
 | |
|     #region  Insert, Remove, Clear
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Gives the new object a parent reference to this
 | |
|     /// list.
 | |
|     /// </summary>
 | |
|     /// <param name="index">Index at which to insert the item.</param>
 | |
|     /// <param name="item">Item to insert.</param>
 | |
|     protected override void InsertItem(int index, T item)
 | |
|     {
 | |
|       item.SetParent(this);
 | |
|       base.InsertItem(index, item);
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Removes an item from the list.
 | |
|     /// </summary>
 | |
|     /// <param name="index">Index of the item
 | |
|     /// to be removed.</param>
 | |
|     protected override void RemoveItem(int index)
 | |
|     {
 | |
|       // delete item from database
 | |
|       T item = this[index];
 | |
| 
 | |
|       // only delete/save the item if it is not new
 | |
|       if (!item.IsNew)
 | |
|       {
 | |
|         item.Delete();
 | |
|         SaveItem(index);
 | |
|       }
 | |
| 
 | |
|       // disconnect event handler if necessary
 | |
|       System.ComponentModel.INotifyPropertyChanged c = item as System.ComponentModel.INotifyPropertyChanged;
 | |
|       if (c != null)
 | |
|       {
 | |
|         c.PropertyChanged -= new System.ComponentModel.PropertyChangedEventHandler(Child_PropertyChanged);
 | |
|       }
 | |
| 
 | |
|       base.RemoveItem(index);
 | |
|     }
 | |
| 
 | |
|     #endregion
 | |
| 
 | |
|     #region  IParent Members
 | |
| 
 | |
|     void Csla.Core.IParent.ApplyEditChild(Core.IEditableBusinessObject child)
 | |
|     {
 | |
|       if (!_activelySaving && child.EditLevel == 0)
 | |
|         SaveItem((T)child);
 | |
|     }
 | |
| 
 | |
|     void Csla.Core.IParent.RemoveChild(Core.IEditableBusinessObject child)
 | |
|     {
 | |
|       // do nothing, removal of a child is handled by
 | |
|       // the RemoveItem override
 | |
|     }
 | |
| 
 | |
|     #endregion
 | |
| 
 | |
|     #region  Cascade Child events
 | |
| 
 | |
|     private void Child_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
 | |
|     {
 | |
|       for (int index = 0; index < this.Count; index++)
 | |
|       {
 | |
|         if (ReferenceEquals(this[index], sender))
 | |
|         {
 | |
|           OnListChanged(new System.ComponentModel.ListChangedEventArgs(System.ComponentModel.ListChangedType.ItemChanged, index));
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     #endregion
 | |
| 
 | |
|     #region  Serialization Notification
 | |
| 
 | |
|     [OnDeserialized()]
 | |
|     private void OnDeserializedHandler(StreamingContext context)
 | |
|     {
 | |
| 
 | |
|       OnDeserialized(context);
 | |
|       foreach (Core.IEditableBusinessObject child in this)
 | |
|       {
 | |
|         child.SetParent(this);
 | |
|         System.ComponentModel.INotifyPropertyChanged c = child as System.ComponentModel.INotifyPropertyChanged;
 | |
|         if (c != null)
 | |
|         {
 | |
|           c.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(Child_PropertyChanged);
 | |
|         }
 | |
|       }
 | |
| 
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// This method is called on a newly deserialized object
 | |
|     /// after deserialization is complete.
 | |
|     /// </summary>
 | |
|     /// <param name="context">Serialization context object.</param>
 | |
|     [EditorBrowsable(EditorBrowsableState.Advanced)]
 | |
|     protected virtual void OnDeserialized(StreamingContext context)
 | |
|     {
 | |
| 
 | |
|       // do nothing - this is here so a subclass
 | |
|       // could override if needed
 | |
| 
 | |
|     }
 | |
| 
 | |
|     #endregion
 | |
| 
 | |
|     #region  Data Access
 | |
| 
 | |
|     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "criteria")]
 | |
|     private void DataPortal_Create(object criteria)
 | |
|     {
 | |
|       throw new NotSupportedException(Properties.Resources.CreateNotSupportedException);
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Override this method to allow retrieval of an existing business
 | |
|     /// object based on data in the database.
 | |
|     /// </summary>
 | |
|     /// <param name="criteria">An object containing criteria values to identify the object.</param>
 | |
|     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", MessageId = "Member")]
 | |
|     protected virtual void DataPortal_Fetch(object criteria)
 | |
|     {
 | |
|       throw new NotSupportedException(Properties.Resources.FetchNotSupportedException);
 | |
|     }
 | |
| 
 | |
|     private void DataPortal_Update()
 | |
|     {
 | |
|       throw new NotSupportedException(Properties.Resources.UpdateNotSupportedException);
 | |
|     }
 | |
| 
 | |
|     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "criteria")]
 | |
|     private void DataPortal_Delete(object criteria)
 | |
|     {
 | |
|       throw new NotSupportedException(Properties.Resources.DeleteNotSupportedException);
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Called by the server-side DataPortal prior to calling the 
 | |
|     /// requested DataPortal_xyz method.
 | |
|     /// </summary>
 | |
|     /// <param name="e">The DataPortalContext object passed to the DataPortal.</param>
 | |
|     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", MessageId = "Member"), EditorBrowsable(EditorBrowsableState.Advanced)]
 | |
|     protected virtual void DataPortal_OnDataPortalInvoke(DataPortalEventArgs e)
 | |
|     {
 | |
| 
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Called by the server-side DataPortal after calling the 
 | |
|     /// requested DataPortal_xyz method.
 | |
|     /// </summary>
 | |
|     /// <param name="e">The DataPortalContext object passed to the DataPortal.</param>
 | |
|     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", MessageId = "Member"), EditorBrowsable(EditorBrowsableState.Advanced)]
 | |
|     protected virtual void DataPortal_OnDataPortalInvokeComplete(DataPortalEventArgs e)
 | |
|     {
 | |
| 
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Called by the server-side DataPortal if an exception
 | |
|     /// occurs during data access.
 | |
|     /// </summary>
 | |
|     /// <param name="e">The DataPortalContext object passed to the DataPortal.</param>
 | |
|     /// <param name="ex">The Exception thrown during data access.</param>
 | |
|     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", MessageId = "Member"), EditorBrowsable(EditorBrowsableState.Advanced)]
 | |
|     protected virtual void DataPortal_OnDataPortalException(DataPortalEventArgs e, Exception ex)
 | |
|     {
 | |
| 
 | |
|     }
 | |
| 
 | |
|     #endregion
 | |
| 
 | |
|   }
 | |
| }
 |