Winforms Data Binding Lessons Learned

Reacting to Illegal Row Deletion in a DataGrid

This part is a little trickier than before, since you can't just throw an exception which is handled by the DataGrid. For some reason you have to go through some hoops to create this kind of functionality yourself. The first trick to understanding how to accomplish this is to understand how the DataGrid displays its data. You should notice that the DataGrid does not have any properties, such as AllowDelete or AllowAddNew. In fact, you can't control how your users should interact with the grid using any of the grid's properties (except Enabled). The trick is that the DataGrid is actually basing its interactivity level on an underlying DataView object to which it is bound. If you look at a DataView object, you should see that it does contain these kinds of properties. So, setting AllowDelete on the DataGrid's underlying DataView object to false disables delete functionality from the grid.

Now, the technique becomes pretty simple: we disable the AllowDelete property of the DataView and catch the KeyDown event of the DataGrid. If the KeyCode is that of the Keys.Delete key, we enable deletion on the DataView, delete the current data row, and disable deletion again until next time. Here's the code:

Private Sub grd_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles grd.KeyDown
    If e.KeyCode = Keys.Delete Then
        'check whether the current DataRow Course
        'is in Progress and cancel deletion if it is
        If IsInProgress(CType(GetGridCurrency().Current, DataRowView).Row) Then
            MsgBox("Already in progress")
        Else
            'Delete the current row
            EnableDelete(True)
            CType(GetGridCurrency().Current, DataRowView).Delete()
            EnableDelete(False)
        End If
    End If
End Sub

Private Function GetGridCurrency() As CurrencyManager
    'return the currency manager associated with the DataGrid
    Dim cm As CurrencyManager = BindingContext(grd.DataSource, grd.DataMember)
    Return cm
End Function

Private Sub EnableDelete(ByVal value As Boolean)
    'enable or disable AllowDelete on the
    'DataGrid() 's underlying DataView
    Dim cm As CurrencyManager = GetGridCurrency()
    Dim view As DataView = CType(cm.List, DataView)
    view.AllowDelete = value
End Sub

Notice that what I'm actually deleting is a DataRowView object, not a DataRow. This is because just like a data table has data rows, a DataView has DataRowViews corresponding to each DataTable row. Each DataRowView holds a property reference to the data row associated with it. Performing actions on a DataRowView is just like performing them on a DataRow object.

That's it. There's no way around this that I could find, but I have seen one other way to accomplish this functionality, by deriving a custom grid from the DataGrid and pre-processing WM_KEYDOWN messages before they arrive.

You might also like...

Comments

About the author

Roy Osherove Israel

Roy Osherove has spent the past 6+ years developing data driven applications for various companies in Israel. He's acquired several MCP titles, written a number of articles on various .NET topic...

Interested in writing for us? Find out more.

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“Memory is like an orgasm. It's a lot better if you don't have to fake it.” - Seymour Cray