Handling DataTable Events
The DataTable object provides a series of events that can be processed by an application. The following table describes DataTable
events.
Event | Description |
---|---|
Initialized | Occurs after the EndInit method of a DataTable is called. This event is intended primarily to support design-time scenarios. |
ColumnChanged | Occurs after a value has been successfully changed in a DataColumn. |
ColumnChanging | Occurs when a value has been submitted for a DataColumn . |
RowChanged | Occurs after a DataColumn value or the RowState of a DataRow in the DataTable has been changed successfully. |
RowChanging | Occurs when a change has been submitted for a DataColumn value or the RowState of a DataRow in the DataTable . |
RowDeleted | Occurs after a DataRow in the DataTable has been marked as Deleted . |
RowDeleting | Occurs before a DataRow in the DataTable is marked as Deleted . |
TableCleared | Occurs after a call to the Clear method of the DataTable has successfully cleared every DataRow . |
TableClearing | Occurs after the Clear method is called but before the Clear operation begins. |
TableNewRow | Occurs after a new DataRow is created by a call to the NewRow method of the DataTable . |
Disposed | Occurs when the DataTable is Disposed . Inherited from MarshalByValueComponent. |
Note
Most operations that add or delete rows do not raise the ColumnChanged
and ColumnChanging
events. However, the ReadXml
method does raise ColumnChanged
and ColumnChanging
events, unless the XmlReadMode
is set to DiffGram
or is set to Auto
when the XML document being read is a DiffGram
.
Warning
Data corruption can occur if data is modified in a DataSet
from which the RowChanged
event is raised. No exception will be raised if such data corruption occurs.
Additional Related Events
The Constraints property holds a ConstraintCollection instance. The ConstraintCollection class exposes a CollectionChanged event. This event fires when a constraint is added, modified, or removed from the ConstraintCollection
.
The Columns property holds a DataColumnCollection instance. The DataColumnCollection
class exposes a CollectionChanged event. This event fires when a DataColumn
is added, modified, or removed from the DataColumnCollection
. Modifications that cause the event to fire include changes to the name, type, expression or ordinal position of a column.
The Tables property of a DataSet holds a DataTableCollection instance. The DataTableCollection
class exposes both a CollectionChanged
and a CollectionChanging
event. These events fire when a DataTable
is added to or removed from the DataSet
.
Changes to DataRows
can also trigger events for an associated DataView. The DataView
class exposes a ListChanged event that fires when a DataColumn
value changes or when the composition or sort order of the view changes. The DataRowView class exposes a PropertyChanged event that fires when an associated DataColumn
value changes.
Sequence of Operations
Here is the sequence of operations that occur when a DataRow
is added, modified, or deleted:
Create the proposed record and apply any changes.
Check constraints for non-expression columns.
Raise the
RowChanging
orRowDeleting
events as applicable.Set the proposed record to be the current record.
Update any associated indexes.
Raise
ListChanged
events for associatedDataView
objects andPropertyChanged
events for associatedDataRowView
objects.Evaluate all expression columns, but delay checking any constraints on these columns.
Raise
ListChanged
events for associatedDataView
objects andPropertyChanged
events for associatedDataRowView
objects affected by the expression column evaluations.Raise
RowChanged
orRowDeleted
events as applicable.Check constraints on expression columns.
Note
Changes to expression columns never raise DataTable
events. Changes to expression columns only raise DataView
and DataRowView
events. Expression columns can have dependencies on multiple other columns, and can be evaluated multiple times during a single DataRow
operation. Each expression evaluation raises events, and a single DataRow
operation can raise multiple ListChanged
and PropertyChanged
events when expression columns are affected, possibly including multiple events for the same expression column.
Warning
Do not throw a NullReferenceException within the RowChanged
event handler. If a NullReferenceException is thrown within the RowChanged
event of a DataTable
, then the DataTable
will be corrupted.
Example
The following example demonstrates how to create event handlers for the RowChanged
, RowChanging
, RowDeleted
, RowDeleting
, ColumnChanged
, ColumnChanging
, TableNewRow
, TableCleared
, and TableClearing
events. Each event handler displays output in the console window when it is fired.
static void DataTableEvents()
{
DataTable table = new("Customers");
// Add two columns, id and name.
table.Columns.Add("id", typeof(int));
table.Columns.Add("name", typeof(string));
// Set the primary key.
table.Columns["id"].Unique = true;
table.PrimaryKey = new DataColumn[] { table.Columns["id"] };
// Add a RowChanged event handler.
table.RowChanged += Row_Changed;
// Add a RowChanging event handler.
table.RowChanging += Row_Changing;
// Add a RowDeleted event handler.
table.RowDeleted += Row_Deleted;
// Add a RowDeleting event handler.
table.RowDeleting += Row_Deleting;
// Add a ColumnChanged event handler.
table.ColumnChanged +=
Column_Changed;
// Add a ColumnChanging event handler.
table.ColumnChanging +=
Column_Changing;
// Add a TableNewRow event handler.
table.TableNewRow +=
Table_NewRow;
// Add a TableCleared event handler.
table.TableCleared +=
Table_Cleared;
// Add a TableClearing event handler.
table.TableClearing +=
Table_Clearing;
// Add a customer.
DataRow row = table.NewRow();
row["id"] = 1;
row["name"] = "Customer1";
table.Rows.Add(row);
table.AcceptChanges();
// Change the customer name.
table.Rows[0]["name"] = "ChangedCustomer1";
// Delete the row.
table.Rows[0].Delete();
// Clear the table.
table.Clear();
}
static void Row_Changed(object sender, DataRowChangeEventArgs e) =>
Console.WriteLine("Row_Changed Event: name={0}; action={1}",
e.Row["name"], e.Action);
static void Row_Changing(object sender, DataRowChangeEventArgs e) =>
Console.WriteLine("Row_Changing Event: name={0}; action={1}",
e.Row["name"], e.Action);
static void Row_Deleted(object sender, DataRowChangeEventArgs e) =>
Console.WriteLine("Row_Deleted Event: name={0}; action={1}",
e.Row["name", DataRowVersion.Original], e.Action);
static void Row_Deleting(object sender,
DataRowChangeEventArgs e) =>
Console.WriteLine("Row_Deleting Event: name={0}; action={1}",
e.Row["name"], e.Action);
static void Column_Changed(object sender, DataColumnChangeEventArgs e) =>
Console.WriteLine("Column_Changed Event: ColumnName={0}; RowState={1}",
e.Column.ColumnName, e.Row.RowState);
static void Column_Changing(object sender, DataColumnChangeEventArgs e) =>
Console.WriteLine("Column_Changing Event: ColumnName={0}; RowState={1}",
e.Column.ColumnName, e.Row.RowState);
static void Table_NewRow(object sender,
DataTableNewRowEventArgs e) =>
Console.WriteLine("Table_NewRow Event: RowState={0}",
e.Row.RowState.ToString());
static void Table_Cleared(object sender, DataTableClearEventArgs e) =>
Console.WriteLine("Table_Cleared Event: TableName={0}; Rows={1}",
e.TableName, e.Table.Rows.Count.ToString());
static void Table_Clearing(object sender, DataTableClearEventArgs e) =>
Console.WriteLine("Table_Clearing Event: TableName={0}; Rows={1}",
e.TableName, e.Table.Rows.Count.ToString());
Private Sub DataTableEvents()
Dim table As New DataTable("Customers")
' Add two columns, id and name.
table.Columns.Add("id", Type.GetType("System.Int32"))
table.Columns.Add("name", Type.GetType("System.String"))
' Set the primary key.
table.Columns("id").Unique = True
table.PrimaryKey = New DataColumn() {table.Columns("id")}
' Add a RowChanged event handler.
AddHandler table.RowChanged, _
New DataRowChangeEventHandler(AddressOf Row_Changed)
' Add a RowChanging event handler.
AddHandler table.RowChanging, _
New DataRowChangeEventHandler(AddressOf Row_Changing)
' Add a RowDeleted event handler.
AddHandler table.RowDeleted, New _
DataRowChangeEventHandler(AddressOf Row_Deleted)
' Add a RowDeleting event handler.
AddHandler table.RowDeleting, New _
DataRowChangeEventHandler(AddressOf Row_Deleting)
' Add a ColumnChanged event handler.
AddHandler table.ColumnChanged, _
New DataColumnChangeEventHandler(AddressOf Column_Changed)
' Add a ColumnChanging event handler for the table.
AddHandler table.ColumnChanging, New _
DataColumnChangeEventHandler(AddressOf Column_Changing)
' Add a TableNewRow event handler.
AddHandler table.TableNewRow, New _
DataTableNewRowEventHandler(AddressOf Table_NewRow)
' Add a TableCleared event handler.
AddHandler table.TableCleared, New _
DataTableClearEventHandler(AddressOf Table_Cleared)
' Add a TableClearing event handler.
AddHandler table.TableClearing, New _
DataTableClearEventHandler(AddressOf Table_Clearing)
' Add a customer.
Dim row As DataRow = table.NewRow()
row("id") = 1
row("name") = "Customer1"
table.Rows.Add(row)
table.AcceptChanges()
' Change the customer name.
table.Rows(0).Item("name") = "ChangedCustomer1"
' Delete the row.
table.Rows(0).Delete()
' Clear the table.
table.Clear()
End Sub
Private Sub Row_Changed(ByVal sender As Object, _
ByVal e As DataRowChangeEventArgs)
Console.WriteLine("Row_Changed Event: name={0}; action={1}", _
e.Row("name"), e.Action)
End Sub
Private Sub Row_Changing(ByVal sender As Object, _
ByVal e As DataRowChangeEventArgs)
Console.WriteLine("Row_Changing Event: name={0}; action={1}", _
e.Row("name"), e.Action)
End Sub
Private Sub Row_Deleted(ByVal sender As Object, _
ByVal e As DataRowChangeEventArgs)
Console.WriteLine("Row_Deleted Event: name={0}; action={1}", _
e.Row("name", DataRowVersion.Original), e.Action)
End Sub
Private Sub Row_Deleting(ByVal sender As Object, _
ByVal e As DataRowChangeEventArgs)
Console.WriteLine("Row_Deleting Event: name={0}; action={1}", _
e.Row("name"), e.Action)
End Sub
Private Sub Column_Changed(ByVal sender As Object, _
ByVal e As DataColumnChangeEventArgs)
Console.WriteLine("Column_Changed Event: ColumnName={0}; RowState={1}", _
e.Column.ColumnName, e.Row.RowState)
End Sub
Private Sub Column_Changing(ByVal sender As Object, _
ByVal e As DataColumnChangeEventArgs)
Console.WriteLine("Column_Changing Event: ColumnName={0}; RowState={1}", _
e.Column.ColumnName, e.Row.RowState)
End Sub
Private Sub Table_NewRow(ByVal sender As Object, _
ByVal e As DataTableNewRowEventArgs)
Console.WriteLine("Table_NewRow Event: RowState={0}", _
e.Row.RowState.ToString())
End Sub
Private Sub Table_Cleared(ByVal sender As Object, _
ByVal e As DataTableClearEventArgs)
Console.WriteLine("Table_Cleared Event: TableName={0}; Rows={1}", _
e.TableName, e.Table.Rows.Count.ToString())
End Sub
Private Sub Table_Clearing(ByVal sender As Object, _
ByVal e As DataTableClearEventArgs)
Console.WriteLine("Table_Clearing Event: TableName={0}; Rows={1}", _
e.TableName, e.Table.Rows.Count.ToString())
End Sub