Prevent DataRow Deletion

G

Guest

Hi!

Scenario: A User deletes a row in a DataTable; a MessageBox comes up and
asks if he/she really wants to delete the row; in case the answer is "no",
the row deletion should be cancelled.

There are straightforward solutions for this scenario when an intelligent
control like the DataGridView is used, because such control exhibits a
"UserDeletingRow" event that provides a CANCEL property to be set to TRUE.

But in case no such control is used, I cannot see a clear solution. I have
searched the newsgroups for this, and I find two proposals:

1) Use the RowDeleted event of the DataRow by calling
DataRow.RejectChanges(). I admit this to be a feasible solution, but it has
nasty side effects, like:

- the row will first be deleted and only then be "un-deleted" - including
possible child rows (possibly several generations of them), that also have to
be un-deleted

- after the delete, a lot of other actions occur, like position changes,
for example, that also have to be undone

I conclude that using RowDeleted is not a good a solution (and I guess that
the architects of the DataGridView would agree, because they provided
something better).

2) Use the RowDeleting event of the DataRow.

This looks better, because the RowDeleting event is called before the row is
actually deleted. But - helas - this event doesn't have a CANCEL property.

In the newsgroups I found a solution based on this idea by David Sceppa
(whom I truely admire), which goes like this (I cite):

*******David Sceppa speaking******

You could trap for the RowDeleting event and call the
DataRow's RejectChanges method if you do not want to allow the
deletion. You could also throw an exception if that's
appropriate in your application.


Here's some sample code I used to accomplish this task:


DataTable tbl = new DataTable();
tbl.Columns.Add("CustomerID");
tbl.Columns.Add("CompanyName");
tbl.LoadDataRow(new object[] {"Comp1", "Company #1"}, true);


tbl.RowDeleting += new DataRowChangeEventHandler(DeleteHandler);
Console.WriteLine(tbl.Rows.Count);
try
{
tbl.Rows[0].Delete();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.WriteLine(tbl.Rows.Count);


static void DeleteHandler(object sender, DataRowChangeEventArgs
e)
{
e.Row.RejectChanges();
throw new Exception("Deletion disallowed");
}


I hope this information proves helpful.

*******End of Citation *******

The point here seems to be to throw the exception. As far as I can see,
RejectChanges() doesn't do anything, because at this point in time, the row
to be deleted still has a RowState of "Unchanged" (this is what my debugger
tells me), and you cannot reject a change that has not yet taken place.

In David's example, to throw an exception does the job, because the row is
deleted *programmatically*, and hence, there is a point where the exception
thrown can be caught. But what can I do when the row is deleted by a user
action, like, pressing the Delete button on a BindingNavigator? I have no
idea where I could catch the exception thrown.

Does anybody have an idea? Thanks for any hints.

Axel Hecker
 
P

Patrice

You could ask confirmation in your UI code before performing the actual
deletion ? What is the control that triggers this ? A button ?

--
Patrice

AxelHecker said:
Hi!

Scenario: A User deletes a row in a DataTable; a MessageBox comes up and
asks if he/she really wants to delete the row; in case the answer is "no",
the row deletion should be cancelled.

There are straightforward solutions for this scenario when an intelligent
control like the DataGridView is used, because such control exhibits a
"UserDeletingRow" event that provides a CANCEL property to be set to TRUE.

But in case no such control is used, I cannot see a clear solution. I have
searched the newsgroups for this, and I find two proposals:

1) Use the RowDeleted event of the DataRow by calling
DataRow.RejectChanges(). I admit this to be a feasible solution, but it
has
nasty side effects, like:

- the row will first be deleted and only then be "un-deleted" - including
possible child rows (possibly several generations of them), that also have
to
be un-deleted

- after the delete, a lot of other actions occur, like position changes,
for example, that also have to be undone

I conclude that using RowDeleted is not a good a solution (and I guess
that
the architects of the DataGridView would agree, because they provided
something better).

2) Use the RowDeleting event of the DataRow.

This looks better, because the RowDeleting event is called before the row
is
actually deleted. But - helas - this event doesn't have a CANCEL property.

In the newsgroups I found a solution based on this idea by David Sceppa
(whom I truely admire), which goes like this (I cite):

*******David Sceppa speaking******

You could trap for the RowDeleting event and call the
DataRow's RejectChanges method if you do not want to allow the
deletion. You could also throw an exception if that's
appropriate in your application.


Here's some sample code I used to accomplish this task:


DataTable tbl = new DataTable();
tbl.Columns.Add("CustomerID");
tbl.Columns.Add("CompanyName");
tbl.LoadDataRow(new object[] {"Comp1", "Company #1"}, true);


tbl.RowDeleting += new DataRowChangeEventHandler(DeleteHandler);
Console.WriteLine(tbl.Rows.Count);
try
{
tbl.Rows[0].Delete();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.WriteLine(tbl.Rows.Count);


static void DeleteHandler(object sender, DataRowChangeEventArgs
e)
{
e.Row.RejectChanges();
throw new Exception("Deletion disallowed");
}


I hope this information proves helpful.

*******End of Citation *******

The point here seems to be to throw the exception. As far as I can see,
RejectChanges() doesn't do anything, because at this point in time, the
row
to be deleted still has a RowState of "Unchanged" (this is what my
debugger
tells me), and you cannot reject a change that has not yet taken place.

In David's example, to throw an exception does the job, because the row is
deleted *programmatically*, and hence, there is a point where the
exception
thrown can be caught. But what can I do when the row is deleted by a user
action, like, pressing the Delete button on a BindingNavigator? I have no
idea where I could catch the exception thrown.

Does anybody have an idea? Thanks for any hints.

Axel Hecker
 
G

Guest

Hi Patrice. As I said in my example, the control that triggers this is the
"Delete"-button in a BindingNavigator. Actually, this button does have a
Click event, but unfortunately, this event only fires when the RowDelete has
already completed (both RowDeleting and RowDeleted events of the DataRow come
before the Click event of the Delete-button of the BindingNavigator).
Consequently, to do anything in the Click event of the Delete-button is of no
use.

Thanks for your comment anyway. Axel.


--
Axel Hecker



Patrice said:
You could ask confirmation in your UI code before performing the actual
deletion ? What is the control that triggers this ? A button ?

--
Patrice

AxelHecker said:
Hi!

Scenario: A User deletes a row in a DataTable; a MessageBox comes up and
asks if he/she really wants to delete the row; in case the answer is "no",
the row deletion should be cancelled.

There are straightforward solutions for this scenario when an intelligent
control like the DataGridView is used, because such control exhibits a
"UserDeletingRow" event that provides a CANCEL property to be set to TRUE.

But in case no such control is used, I cannot see a clear solution. I have
searched the newsgroups for this, and I find two proposals:

1) Use the RowDeleted event of the DataRow by calling
DataRow.RejectChanges(). I admit this to be a feasible solution, but it
has
nasty side effects, like:

- the row will first be deleted and only then be "un-deleted" - including
possible child rows (possibly several generations of them), that also have
to
be un-deleted

- after the delete, a lot of other actions occur, like position changes,
for example, that also have to be undone

I conclude that using RowDeleted is not a good a solution (and I guess
that
the architects of the DataGridView would agree, because they provided
something better).

2) Use the RowDeleting event of the DataRow.

This looks better, because the RowDeleting event is called before the row
is
actually deleted. But - helas - this event doesn't have a CANCEL property.

In the newsgroups I found a solution based on this idea by David Sceppa
(whom I truely admire), which goes like this (I cite):

*******David Sceppa speaking******

You could trap for the RowDeleting event and call the
DataRow's RejectChanges method if you do not want to allow the
deletion. You could also throw an exception if that's
appropriate in your application.


Here's some sample code I used to accomplish this task:


DataTable tbl = new DataTable();
tbl.Columns.Add("CustomerID");
tbl.Columns.Add("CompanyName");
tbl.LoadDataRow(new object[] {"Comp1", "Company #1"}, true);


tbl.RowDeleting += new DataRowChangeEventHandler(DeleteHandler);
Console.WriteLine(tbl.Rows.Count);
try
{
tbl.Rows[0].Delete();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.WriteLine(tbl.Rows.Count);


static void DeleteHandler(object sender, DataRowChangeEventArgs
e)
{
e.Row.RejectChanges();
throw new Exception("Deletion disallowed");
}


I hope this information proves helpful.

*******End of Citation *******

The point here seems to be to throw the exception. As far as I can see,
RejectChanges() doesn't do anything, because at this point in time, the
row
to be deleted still has a RowState of "Unchanged" (this is what my
debugger
tells me), and you cannot reject a change that has not yet taken place.

In David's example, to throw an exception does the job, because the row is
deleted *programmatically*, and hence, there is a point where the
exception
thrown can be caught. But what can I do when the row is deleted by a user
action, like, pressing the Delete button on a BindingNavigator? I have no
idea where I could catch the exception thrown.

Does anybody have an idea? Thanks for any hints.

Axel Hecker
 
G

Guest

Pratrice, after rethinking and a closer a look at the the properties of the
BindingNavigator, your question lead me to the solution: the automatic delete
action of the Delete button of the BindingNavigator can be disabled by
setting the DeleteItem property to nothing and then use the Click event of
the Delete button (where I have full control on further actions).

Sorry, things go crazy ways. Thanks again, your question helped me a lot.
--
Axel Hecker



AxelHecker said:
Hi Patrice. As I said in my example, the control that triggers this is the
"Delete"-button in a BindingNavigator. Actually, this button does have a
Click event, but unfortunately, this event only fires when the RowDelete has
already completed (both RowDeleting and RowDeleted events of the DataRow come
before the Click event of the Delete-button of the BindingNavigator).
Consequently, to do anything in the Click event of the Delete-button is of no
use.

Thanks for your comment anyway. Axel.


--
Axel Hecker



Patrice said:
You could ask confirmation in your UI code before performing the actual
deletion ? What is the control that triggers this ? A button ?

--
Patrice

AxelHecker said:
Hi!

Scenario: A User deletes a row in a DataTable; a MessageBox comes up and
asks if he/she really wants to delete the row; in case the answer is "no",
the row deletion should be cancelled.

There are straightforward solutions for this scenario when an intelligent
control like the DataGridView is used, because such control exhibits a
"UserDeletingRow" event that provides a CANCEL property to be set to TRUE.

But in case no such control is used, I cannot see a clear solution. I have
searched the newsgroups for this, and I find two proposals:

1) Use the RowDeleted event of the DataRow by calling
DataRow.RejectChanges(). I admit this to be a feasible solution, but it
has
nasty side effects, like:

- the row will first be deleted and only then be "un-deleted" - including
possible child rows (possibly several generations of them), that also have
to
be un-deleted

- after the delete, a lot of other actions occur, like position changes,
for example, that also have to be undone

I conclude that using RowDeleted is not a good a solution (and I guess
that
the architects of the DataGridView would agree, because they provided
something better).

2) Use the RowDeleting event of the DataRow.

This looks better, because the RowDeleting event is called before the row
is
actually deleted. But - helas - this event doesn't have a CANCEL property.

In the newsgroups I found a solution based on this idea by David Sceppa
(whom I truely admire), which goes like this (I cite):

*******David Sceppa speaking******

You could trap for the RowDeleting event and call the
DataRow's RejectChanges method if you do not want to allow the
deletion. You could also throw an exception if that's
appropriate in your application.


Here's some sample code I used to accomplish this task:


DataTable tbl = new DataTable();
tbl.Columns.Add("CustomerID");
tbl.Columns.Add("CompanyName");
tbl.LoadDataRow(new object[] {"Comp1", "Company #1"}, true);


tbl.RowDeleting += new DataRowChangeEventHandler(DeleteHandler);
Console.WriteLine(tbl.Rows.Count);
try
{
tbl.Rows[0].Delete();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.WriteLine(tbl.Rows.Count);


static void DeleteHandler(object sender, DataRowChangeEventArgs
e)
{
e.Row.RejectChanges();
throw new Exception("Deletion disallowed");
}


I hope this information proves helpful.

*******End of Citation *******

The point here seems to be to throw the exception. As far as I can see,
RejectChanges() doesn't do anything, because at this point in time, the
row
to be deleted still has a RowState of "Unchanged" (this is what my
debugger
tells me), and you cannot reject a change that has not yet taken place.

In David's example, to throw an exception does the job, because the row is
deleted *programmatically*, and hence, there is a point where the
exception
thrown can be caught. But what can I do when the row is deleted by a user
action, like, pressing the Delete button on a BindingNavigator? I have no
idea where I could catch the exception thrown.

Does anybody have an idea? Thanks for any hints.

Axel Hecker
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top