我想对列表框项目的拖放操作提出一些建议。我的每个项目都有一个ComboBox,TextBox,CheckBox和Button,如下所示。
我使用拖放功能对这些进行重新排序,它几乎正常工作。
主要问题是当上述一个控件上发生PreviewMouseLeftButtonDown和PreviewMouseMove事件时,正在对项目执行拖动操作。
我的问题是下面的代码,当我点击其中一个控件时,我可以阻止这种拖拽的好方法吗?
XAML:
<DataTemplate DataType="{x:Type helpers:Filter}">
<Border>
<Border>
<Grid>
<ComboBox />
<TextBox />
<CheckBox />
<Button />
</Grid>
</Border>
</Border>
</DataTemplate>
<ListBox x:Name="FilterList"
ItemsSource="{Binding Filters}"
helpers:DragDropHelper.IsDragSource="true"
helpers:DragDropHelper.IsDropTarget="true" />
C#:
public static readonly DependencyProperty IsDragSourceProperty =
DependencyProperty.RegisterAttached("IsDragSource", typeof(bool), typeof(DragDropHelper), new UIPropertyMetadata(false, IsDragSourceChanged));
private void DragSource_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
this.sourceItemsControl = (ItemsControl)sender;
Visual visual = e.OriginalSource as Visual;
this.topWindow = Window.GetWindow(this.sourceItemsControl);
this.initialMousePosition = e.GetPosition(this.topWindow);
this.sourceItemContainer = sourceItemsControl.ContainerFromElement(visual) as FrameworkElement;
if (this.sourceItemContainer != null)
{
this.draggedData = this.sourceItemContainer.DataContext;
}
}
// Drag = mouse down + move by a certain amount
private void DragSource_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (this.draggedData != null)
{
// Only drag when user moved the mouse by a reasonable amount.
if (Utilities.IsMovementBigEnough(this.initialMousePosition, e.GetPosition(this.topWindow)))
{
this.initialMouseOffset = this.initialMousePosition - this.sourceItemContainer.TranslatePoint(new Point(0, 0), this.topWindow);
DataObject data = new DataObject(this.format.Name, this.draggedData);
// Adding events to the window to make sure dragged adorner comes up when mouse is not over a drop target.
bool previousAllowDrop = this.topWindow.AllowDrop;
this.topWindow.AllowDrop = true;
this.topWindow.DragEnter += TopWindow_DragEnter;
this.topWindow.DragOver += TopWindow_DragOver;
this.topWindow.DragLeave += TopWindow_DragLeave;
DragDropEffects effects = DragDrop.DoDragDrop((DependencyObject)sender, data, DragDropEffects.Move);
RemoveDraggedAdorner();
this.topWindow.AllowDrop = previousAllowDrop;
this.topWindow.DragEnter -= TopWindow_DragEnter;
this.topWindow.DragOver -= TopWindow_DragOver;
this.topWindow.DragLeave -= TopWindow_DragLeave;
this.draggedData = null;
}
}
}
答案 0 :(得分:2)
我倾向于在PreviewMouseDown
事件处理程序中初始化我的拖放属性,但在该处理程序中执行任何其他拖放操作是不明智的,因为用户可能没有拖动...他们可能只是点击了。
相反,最好处理PreviewMouseMove
事件以启动拖放操作。这是一个简化的例子:
private void DragSourcePreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
isMouseDown = true;
}
private void DragSourcePreviewMouseMove(object sender, MouseEventArgs e)
{
if (isMouseDown && IsConfirmedDrag(e.GetPosition(sender as ListBox)))
{
isMouseDown = false;
...
DragDrop.DoDragDrop(dragSource, data, DragDropEffects);
}
}
在PreviewMouseMove
事件处理程序中,您可以检查单击了哪个UI元素,并确定是否启动了拖放操作。尝试这样的事情:
private void DragSourcePreviewMouseMove(object sender, MouseEventArgs e)
{
ListBox dragSourceControl = (ListBox)sender;
HitTestResult result = VisualTreeHelper.HitTest(dragSourceControl,
Mouse.GetPosition(dragSourceControl));
UIElement draggedUIElement = result.VisualHit.GetParentOfType<ListBoxItem>();
bool isViable = AddYourViabilityConditionHere(draggedUIElement);
if (isMouseDown && IsConfirmedDrag(e.GetPosition(sender as ListBox)) && isViable)
{
isMouseDown = false;
...
DragDrop.DoDragDrop(dragSource, data, DragDropEffects);
}
}