using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization;
using System.ComponentModel;
namespace Csla
{
///
/// This is the base class from which collections
/// of editable root business objects should be
/// derived.
///
///
/// Type of editable root object to contain within
/// the collection.
///
///
///
/// Your subclass should implement a factory method
/// and should override or overload
/// DataPortal_Fetch() to implement data retrieval.
///
/// Saving (inserts or updates) of items in the collection
/// should be handled through the SaveItem() method on
/// the collection.
///
/// 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.
///
///
[Serializable()]
public abstract class EditableRootListBase : Core.ExtendedBindingList, Core.IParent
where T : Core.IEditableBusinessObject, Core.ISavable
{
#region SaveItem Methods
private bool _activelySaving;
///
/// Saves the specified item in the list.
///
///
/// Reference to the item to be saved.
///
///
/// 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.
///
public void SaveItem(T item)
{
SaveItem(IndexOf(item));
}
///
/// Saves the specified item in the list.
///
///
/// Index of the item to be saved.
///
///
/// 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.
///
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
///
/// Gives the new object a parent reference to this
/// list.
///
/// Index at which to insert the item.
/// Item to insert.
protected override void InsertItem(int index, T item)
{
item.SetParent(this);
base.InsertItem(index, item);
}
///
/// Removes an item from the list.
///
/// Index of the item
/// to be removed.
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);
}
}
}
///
/// This method is called on a newly deserialized object
/// after deserialization is complete.
///
/// Serialization context object.
[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);
}
///
/// Override this method to allow retrieval of an existing business
/// object based on data in the database.
///
/// An object containing criteria values to identify the object.
[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);
}
///
/// Called by the server-side DataPortal prior to calling the
/// requested DataPortal_xyz method.
///
/// The DataPortalContext object passed to the DataPortal.
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", MessageId = "Member"), EditorBrowsable(EditorBrowsableState.Advanced)]
protected virtual void DataPortal_OnDataPortalInvoke(DataPortalEventArgs e)
{
}
///
/// Called by the server-side DataPortal after calling the
/// requested DataPortal_xyz method.
///
/// The DataPortalContext object passed to the DataPortal.
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", MessageId = "Member"), EditorBrowsable(EditorBrowsableState.Advanced)]
protected virtual void DataPortal_OnDataPortalInvokeComplete(DataPortalEventArgs e)
{
}
///
/// Called by the server-side DataPortal if an exception
/// occurs during data access.
///
/// The DataPortalContext object passed to the DataPortal.
/// The Exception thrown during data access.
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", MessageId = "Member"), EditorBrowsable(EditorBrowsableState.Advanced)]
protected virtual void DataPortal_OnDataPortalException(DataPortalEventArgs e, Exception ex)
{
}
#endregion
}
}