Improving the drag and drop behaviour of WPF datagrid





5.00/5 (1 vote)
Change the visual feed back when dragging a non freezable column in to frozen column or Vice versa
The default behavior of the datagrid is that when the user drags across a non frozen column into a frozen column or the other way around, the cursor seems to disappear which causes confusion among the users. This article demonstrates a way of solving this problem by providing a blocked cursor, which provides a clear indication to the user that the operation is not permitted.
The solution depends on the three main events exposed by the data grid namely
ColumnHeaderDragStarted
, ColumnHeaderDragCompleted
, ColumnHeaderDragDelta
.
One another approach would be to use the preview mouse events but it has its problems in that these events are not fired during drag and drop unless you set the PreviewMouseLeftButtonDown
as handled. In case PreviewMouseLeftButtonDown
is marked as handled, then the whole drag and drop functionality will have to be implemented by the developer.
The solution proposed determines the location of the cursor and changes it appropriately after a few calculations.
The following code shows the key events:
void DataGrid_ColumnHeaderDragDelta(object sender, DragDeltaEventArgs e)
{
currentHorizontalOffset += e.HorizontalChange;
// Cannot drag a normal column to a frozen column
if (currentHorizontalOffset < totalFrozenColumnsWidth && isDraggingNormalColumn)
{
Mouse.OverrideCursor = Cursors.No;
}
// Cannot drag a frozen column inside a normal column
else if (currentHorizontalOffset > totalFrozenColumnsWidth && !isDraggingNormalColumn)
{
Mouse.OverrideCursor = Cursors.No;
}
// dragging possible
else
{
Mouse.OverrideCursor = Cursors.Arrow;
}
}
void DataGrid_ColumnHeaderDragCompleted(object sender, DragCompletedEventArgs e)
{
// Restore everything
totalFrozenColumnsWidth = 0;
currentHorizontalOffset = 0;
Mouse.OverrideCursor = previousCursor;
isDraggingNormalColumn = false;
}
void DataGrid_ColumnHeaderDragStarted(object sender, DragStartedEventArgs e)
{
// Store the current cursor so we can restore it later
previousCursor = Mouse.OverrideCursor;
currentHorizontalOffset = e.HorizontalOffset;
// The frozen columns will be at the top of the collection
if (FrozenColumnCount > 0)
{
totalFrozenColumnsWidth = this.Columns.Take(FrozenColumnCount).Sum(c => c.ActualWidth);
}
isDraggingNormalColumn = (currentHorizontalOffset > totalFrozenColumnsWidth) ? true : false;
}