Send a suggestion!

We're building a brand new version of the site, and we'd love to hear your ideas

Members

Technology Zones

IBM Learning Center

Articles

Hosted By

MaximumASP

Info

Rated
Read 65,029 times

Contents

Related Categories

Winforms Data Binding Lessons Learned - Reacting to Illegal Row Deletion in a DataGrid

RoyOsherove

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.

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 topics, most of which can be found on his weblog, and loves discovering new things everyday. Roy is also the author of the Feedable service and of the free regular expression tool, The Regulator.

Comments

  • Re: [4491] A MUCH easier way

    Posted by davidhere40 on 22 May 2007

    I didn't like any of the solutions to this problem until I came up with this one...

    The solution is to bind the entire Child table to a bindingSource and that to a dataGridView.  In this c...

  • Re: your dataview index does not sync with cm index

    Posted by nhrones on 04 Oct 2006

    Use a BindingSource control then use its Find method to get the index of the row.

  • Re: [4491] Winforms Data Binding Lessons Learned

    Posted by dloiac1 on 31 Mar 2006

    I'm getting this error message: "Object reference not set to an instance of an object." when I try to run the code below. I've spent a couple days trying to figure out what it is, but I'm kind of&n...

  • You save me from getting crazy

    Posted by jmeile on 24 Sep 2005

    Well, not really. I'm exagerating a litte bit ;)

    Anyway, I just want to thank you for this nice and realy usefull article.
    I not only got the relationships shown in a DataGrid, but also I could
    ...

  • Posted by Jo_dc on 27 Jul 2005

    try
    Private view As DataView = m_ds.Tables("Stuff").DefaultView

    But anyway I think that the trick is that the field ID is PK