简体   繁体   English

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

[英]How to prevent listbox items being dragged if mouse down is on certain controls

I would like some advice on drag and drop operations of listbox items. 我想要一些有关列表框项目的拖放操作的建议。 Each of my items has a ComboBox, TextBox, CheckBox and Button, as shown below. 我的每个项目都有一个ComboBox,TextBox,CheckBox和Button,如下所示。

在此处输入图片说明

I use my drag/drop to reorder these and it is almost working correctly. 我使用拖放操作重新排序,它们几乎可以正常工作。

The main issue is that a drag operation on an item is occurring when a PreviewMouseLeftButtonDown and PreviewMouseMove event happens on one of the controls noted above. 主要问题是,当在上面提到的控件之一上发生PreviewMouseLeftButtonDown和PreviewMouseMove事件时,正在对项目进行拖动操作。

My question is given the code below what's good way I can prevent this drag occuring when one of the controls is clicked on? 下面的代码给出了我的问题,当单击其中一个控件时,有什么好的方法可以防止这种拖动发生?

XAML: 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#: 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;
        }
    }
}

I tend to initialise my Drag and Drop properties in a PreviewMouseDown event handler, but it's unwise to perform any other Drag and Drop operations in that handler, because the user might not be dragging... they might just have clicked. 我倾向于在PreviewMouseDown事件处理程序中初始化我的拖放属性,但是在该处理程序中执行任何其他拖放操作是不明智的,因为用户可能不会拖动...他们可能只是单击了。

Instead, it's better to handle the PreviewMouseMove event to initiate a Drag and Drop operation. 相反,最好处理PreviewMouseMove事件以启动拖放操作。 Here is a simplified example: 这是一个简化的示例:

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

It is in the PreviewMouseMove event handler that you could check which UI element has been clicked on and determine whether you start the Drag and Drop operation or not. 您可以在PreviewMouseMove事件处理程序中检查单击了哪个UI元素,并确定是否启动拖放操作。 Try something like this: 尝试这样的事情:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM