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.
Comments