编辑模式下禁用DataGrid单元格内的拖放功能
问题解决思路与方案
你的核心问题是DataGrid单元格编辑时误触发拖放,以及多次点击引发的异常,根源在于MouseMove事件没有区分「点击编辑」和「拖动操作」,且编辑状态下的TextBox默认允许拖放。以下是针对性的解决步骤:
1. 区分拖动与点击,增加拖放阈值
通过记录鼠标按下的初始位置,只有当鼠标移动超过系统最小拖动距离时才触发拖放,避免点击编辑时误触发。
步骤1:添加MouseDown事件记录起点
在DataGridRow的Style中添加MouseDown事件绑定:
<Style TargetType="DataGridRow"> <EventSetter Event="MouseDoubleClick" Handler="DGBottleListRow_DoubleClick"/> <EventSetter Event="MouseMove" Handler="DGBottleListRow_MouseMove"/> <EventSetter Event="MouseDown" Handler="DGBottleListRow_MouseDown"/> </Style>
步骤2:后台记录并判断拖动距离
在窗口类中添加私有变量记录起点,修改MouseMove事件:
private Point _dragStartPoint; protected void DGBottleListRow_MouseDown(object sender, MouseButtonEventArgs e) { if (e.LeftButton == MouseButtonState.Pressed) _dragStartPoint = e.GetPosition(null); } protected void DGBottleListRow_MouseMove(object sender, MouseEventArgs e) { if (sender is not DataGridRow row) return; // 编辑状态下直接跳过拖放逻辑 if (row.IsEditing || DGBottleList.IsEditing) return; if (row.Item is not WineBottle movedBottle) return; if (e.LeftButton == MouseButtonState.Pressed) { Point currentPoint = e.GetPosition(null); // 超过系统最小拖动距离才触发拖放 if (Math.Abs(currentPoint.X - _dragStartPoint.X) > SystemParameters.MinimumHorizontalDragDistance || Math.Abs(currentPoint.Y - _dragStartPoint.Y) > SystemParameters.MinimumVerticalDragDistance) { DragDrop.DoDragDrop(row, movedBottle.ID.ToString(), DragDropEffects.Move); } } }
2. 禁用编辑控件的拖放行为
DataGrid进入编辑状态时,单元格内的TextBox默认允许拖放,需要显式禁用:
为可编辑列设置EditingElementStyle
对所有非ReadOnly的DataGridTextColumn添加编辑样式:
<DataGridTextColumn Header="Name" Binding="{Binding Name}" Width="SizeToCells" MinWidth="45"> <DataGridTextColumn.EditingElementStyle> <Style TargetType="TextBox"> <Setter Property="AllowDrop" Value="False"/> <EventSetter Event="PreviewDragOver" Handler="TextBox_PreviewDragOver"/> <EventSetter Event="PreviewDrop" Handler="TextBox_PreviewDrop"/> </Style> </DataGridTextColumn.EditingElementStyle> </DataGridTextColumn> <!-- 其他可编辑列(Vineyard、Vintage、Varietal、Region)同样添加此样式 -->
后台阻止拖放事件
添加事件处理确保拖放操作被完全阻止:
protected void TextBox_PreviewDragOver(object sender, DragEventArgs e) { e.Handled = true; } protected void TextBox_PreviewDrop(object sender, DragEventArgs e) { e.Handled = true; }
3. 额外异常防护
在拖放方法外层添加try-catch,避免多次触发导致未处理异常:
if (Math.Abs(currentPoint.X - _dragStartPoint.X) > SystemParameters.MinimumHorizontalDragDistance || Math.Abs(currentPoint.Y - _dragStartPoint.Y) > SystemParameters.MinimumVerticalDragDistance) { try { DragDrop.DoDragDrop(row, movedBottle.ID.ToString(), DragDropEffects.Move); } catch (Exception ex) { // 可记录日志或静默处理,避免程序崩溃 Debug.WriteLine($"拖放异常:{ex.Message}"); } }
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

