My application is a wine bottle/wine rack tracking tool that allows the user to quickly look up the location of a specific bottle of wine inside a collection of wine racks. I have drag and drop from the list of wine bottles (a DataGrid) to a wine rack (user control) by sending the bottle's ID (int) to the destination control. The problem is when the user clicks on a cell in the DataGrid to edit it's contents the drag drop executes and inserts the bottle ID into the text where the user clicks.
Here is my UI:
This is what happens when I single click on a cell to edit:
If the user clicks multiple times on the cell I get this exception:
Below is the XAML for the DataGrid:
<DataGrid Name="DGBottleList"
Grid.Column="0"
Grid.Row="0"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto"
ItemsSource="{Binding Source=mainWindowBottles}"
IsSynchronizedWithCurrentItem="True"
SelectionChanged="DGBottleList_OnSelectionChanged"
CurrentCellChanged="DGBottleList_CellChanged"
AutoGenerateColumns="False"
Padding="0,0,0,0"
Margin="0,0,5,0">
<DataGrid.Resources>
<Style TargetType="DataGridRow">
<EventSetter Event="MouseDoubleClick" Handler="DGBottleListRow_DoubleClick"/>
<EventSetter Event="MouseMove" Handler="DGBottleListRow_MouseMove"/>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Header="Name"
Binding="{Binding Name}"
Width="SizeToCells"
MinWidth="45"/>
<DataGridTextColumn Header="Vineyard"
Binding="{Binding Vineyard}"
Width="SizeToCells"
MinWidth="55"/>
<DataGridTextColumn Header="Vintage"
Binding="{Binding Vintage}"
Width="SizeToCells"
MinWidth="50"/>
<DataGridTextColumn Header="Varietal"
Binding="{Binding Varietal}"
Width="SizeToCells"
MinWidth="50"/>
<DataGridTextColumn Header="Type"
Binding="{Binding TypeText}"
Width="SizeToCells"
MinWidth="35"
IsReadOnly="True"/>
<DataGridTextColumn Header="Region"
Binding="{Binding Region}"
Width="SizeToCells"
MinWidth="50"/>
<DataGridTextColumn Header="Rack"
Binding="{Binding RackName}"
Width="SizeToCells"
MinWidth="35"
IsReadOnly="True"/>
</DataGrid.Columns>
<DataGrid.ContextMenu>
<ContextMenu>
<MenuItem Header="Copy Bottle" Click="DGBottleList_CopyBottle"/>
<MenuItem Header="Copy Many..." Click="DGBottleList_CopyMany"/>
<Separator/>
<MenuItem Header="Add or Edit Note" Click="DGBottleList_AddNote"/>
<MenuItem Header="Remove from rack" Click="DGBottleList_RemoveFromRack"/>
<Separator/>
<MenuItem Header="Delete" Click="DGBottleList_Delete"/>
</ContextMenu>
</DataGrid.ContextMenu>
</DataGrid>
And here is my MouseMove:
protected void DGBottleListRow_MouseMove(object sender, MouseEventArgs e)
{
if (sender is not DataGridRow row)
return;
if (row.Item is not WineBottle movedBottle)
return;
if (e.LeftButton == MouseButtonState.Pressed)
DragDrop.DoDragDrop(row, movedBottle.ID.ToString(), DragDropEffects.Move);
}
My understanding is the default AllowDrop should be False on the DataGrid and it's children. I have tried manually setting the AllowDrop to false on the DataGrid, DataGridRow, DataGridCell and the TextBlock child. I have tried assigning a handler method to all the before mentioned UI Elements that simply displays a MessageBox when a Drop happens to narrow down where the problem is coming from. I have not been able to get the MessageBox to fire yet. I am at a loss and any help would be appreciated. Thanks!
DataGridRow
has an IsEditing
dependency property. You could check if row is not being edited before DragDrop.DoDragDrop
if (e.LeftButton == MouseButtonState.Pressed && !row.IsEditing)
DragDrop.DoDragDrop(row, movedBottle.ID.ToString(), DragDropEffects.Move);