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
|
|
|
|
}
|
|
}
|