如果在某些控件上按下鼠标,如何防止拖动列表框项目

时间:2014-08-15 02:07:44

标签: c# wpf

我想对列表框项目的拖放操作提出一些建议。我的每个项目都有一个ComboBox,TextBox,CheckBox和Button,如下所示。

enter image description here

我使用拖放功能对这些进行重新排序,它几乎正常工作。

主要问题是当上述一个控件上发生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;
        }
    }
}

1 个答案:

答案 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);
    }
}