private void OnRowChanging(object sender, DataRowChangeEventArgs args)
{
// We foliate the region each time the assocaited row gets deleted
DataRow row = args.Row;
if (args.Action == DataRowAction.Delete && row.Element != null)
{
OnDeletingRow(row, row.Element);
return;
}
if (_ignoreDataSetEvents)
return;
bool wasFoliationEnabled = IsFoliationEnabled;
IsFoliationEnabled = false;
try
{
_ignoreXmlEvents = true;
XmlElement rowElement = GetElementFromRow(row);
int nRec1 = -1;
int nRec2 = -1;
if (rowElement != null)
{
switch (args.Action)
{
case DataRowAction.Add:
// DataRow is beeing added to the table (Table.Rows.Add is beeing called)
break;
case DataRowAction.Delete:
// DataRow is beeing deleted
// - state transition from New (AKA PendingInsert) to Detached (AKA Created)
// - state transition from Unchanged to Deleted (AKA PendingDelete)
// - state transition from Modified (AKA PendingChange) to Delete (AKA PendingDelete)
Debug.Assert(false); // This should have been handled above, irrespective of ignoreDataSetEvents value (true or false)
break;
case DataRowAction.Rollback:
// DataRow gets reverted to previous values (by calling DataRow.RejectChanges):
// - state transition from Detached (AKA Created) to Detached (AKA Created)
// - state transition from New (AKA PendingInsert) to Detached (AKA Created)
// - state transition from Modified (AKA PendingChange) to Unchanged
// - state transition from Deleted (AKA PendingDelete) to Unchanged
_rollbackState = row.RowState;
switch (_rollbackState)
{
case DataRowState.Deleted:
break;
case DataRowState.Detached:
break;
case DataRowState.Added:
break;
case DataRowState.Modified:
_columnChangeList.Clear();
nRec1 = row.GetRecordFromVersion(DataRowVersion.Original);
nRec2 = row.GetRecordFromVersion(DataRowVersion.Current);
foreach (DataColumn c in row.Table.Columns)
{
if (!IsSame(c, nRec1, nRec2))
_columnChangeList.Add(c);
}
break;
}
break;
case DataRowAction.Change:
// A DataRow field is beeing changed
// - state transition from New (AKA PendingInsert) to New (AKA PendingInsert)
// - state transition from Unchanged to Modified (AKA PendingChange)
// - state transition from Modified (AKA PendingChange) to Modified (AKA PendingChange)
_columnChangeList.Clear();
nRec1 = row.GetRecordFromVersion(DataRowVersion.Proposed);
nRec2 = row.GetRecordFromVersion(DataRowVersion.Current);
foreach (DataColumn c in row.Table.Columns)
{
object proposedValue = row[c, DataRowVersion.Proposed];
object currentValue = row[c, DataRowVersion.Current];
// Foliate if proposedValue is DBNull; this way the DataPointer objects will point to a disconnected fragment after
// the DBNull value is beeing set
if (Convert.IsDBNull(proposedValue) && !Convert.IsDBNull(currentValue))
{
// Foliate only for non-hidden columns (since hidden cols are not represented in XML)
if (c.ColumnMapping != MappingType.Hidden)
FoliateIfDataPointers(row, rowElement);
}
if (!IsSame(c, nRec1, nRec2))
_columnChangeList.Add(c);
}
break;
case DataRowAction.Commit:
break;
}
}
}
finally
{
_ignoreXmlEvents = false;
IsFoliationEnabled = wasFoliationEnabled;
}
}