C#WPF鼠标点击事件

时间:2018-01-19 19:30:24

标签: c# wpf events button click

我正在使用带有WPF的C#。我有一个按钮网格,我需要执行以下操作:如果用户按下一个按钮,移动光标并在另一个按钮上释放它,第一个按钮的内容将移动到另一个按钮,类似于拖动。

我尝试使用previewmousedown和previewmouseup按钮事件来了解按下鼠标的按钮以及释放它的按钮,但是按下鼠标的按钮也触发了previewmouseup事件(而不是按下鼠标的按钮)鼠标被释放)。

有关如何以其他方式实现此问题的任何想法,好吗?非常感谢。

2 个答案:

答案 0 :(得分:1)

最简单的拖拉方式drop是内置的DragDrop API。以下是您的概念验证,通常可以点击按钮 *和* 来交换其内容。

如果您想更改行为以便复制或移动内容(而不是交换),只需更改OnButtonDrop中评论下的行。

<强> ButtonDragging.xaml:

<Window x:Class="WpfTest2.ButtonDragging"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <DockPanel LastChildFill="True">
    <Label x:Name="_statusLabel" DockPanel.Dock="Bottom" Content=" " />
    <Grid x:Name="_grid" />
  </DockPanel>
</Window>

<强> ButtonDragging.xaml.cs:

public partial class ButtonDragging
{
    private Button _mouseDownButton;
    private Point _mouseDownLocation;

    public ButtonDragging()
    {
        InitializeComponent();
        BuildButtonGrid();
    }

    private void BuildButtonGrid()
    {
        const int rows = 5;
        const int columns = 5;

        var starLength = new GridLength(1d, GridUnitType.Star);

        for (var i = 0; i < rows; i++)
            _grid.RowDefinitions.Add(new RowDefinition { Height = starLength });

        for (var i = 0; i < columns; i++)
            _grid.ColumnDefinitions.Add(new ColumnDefinition { Width = starLength });

        for (var i = 0; i < rows; i++)
        {
            for (var j = 0; j < columns; j++)
            {
                var button = new Button { Content = $@"({i}, {j})", AllowDrop = true };

                Grid.SetColumn(button, i);
                Grid.SetRow(button, j);

                button.PreviewMouseMove += OnButtonMouseMove;
                button.PreviewMouseLeftButtonDown += OnButtonLeftButtonDown;
                button.PreviewMouseLeftButtonUp += OnButtonLeftButtonUp;
                button.Drop += OnButtonDrop;
                button.Click += OnButtonClick;
                button.LostMouseCapture += OnButtonLostMouseCapture;

                _grid.Children.Add(button);
            }
        }
    }

    private void OnButtonClick(object sender, RoutedEventArgs e)
    {
        _statusLabel.Content = $@"You clicked {(sender as Button)?.Content}!";
    }

    private void ClearPendingDrag()
    {
        _mouseDownButton = null;
        _mouseDownLocation = default(Point);
    }

    private void OnButtonDrop(object sender, DragEventArgs e)
    {
        ClearPendingDrag();

        var source = e.Data.GetData(typeof(object)) as Button;
        if (source == null)
            return;

        var target = (Button)sender;
        if (target == source)
            return;

        var sourceContent = source.Content;
        var targetContent = target.Content;

        // As a proof of concept, this swaps the content of the source and target.
        // Change as necessary to get the behavior you want.

        target.Content = sourceContent;
        source.Content = targetContent;

        _statusLabel.Content = $@"You swapped {sourceContent} with {targetContent}!";
    }

    private void OnButtonLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        var button = (Button)sender;

        _mouseDownButton = button;
        _mouseDownLocation = e.GetPosition(button);

        if (!Mouse.Capture(button, CaptureMode.SubTree))
            ClearPendingDrag();
    }

    private void OnButtonLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        ClearPendingDrag();
    }

    private void OnButtonMouseMove(object sender, MouseEventArgs e)
    {
        if (_mouseDownButton == null)
            return;

        var position = e.GetPosition(_mouseDownButton);
        var distance = position - _mouseDownLocation;

        if (Math.Abs(distance.X) > SystemParameters.MinimumHorizontalDragDistance ||
            Math.Abs(distance.Y) > SystemParameters.MinimumVerticalDragDistance)
        {
            var button = (Button)sender;
            var data = new DataObject(typeof(object), button);

            data.SetData("Source", sender);

            DragDrop.DoDragDrop(button, data, DragDropEffects.Move);

            ClearPendingDrag();
        }
    }

    private void OnButtonLostMouseCapture(object sender, MouseEventArgs e)
    {
        ClearPendingDrag();
    }
}

请注意,可能存在一些对MVVM更友好的第三方(和开源)拖放解决方案。这值得一试,但这应该可以为您提供最低限度的可交付成果。

答案 1 :(得分:-1)

看一下这篇博客文章。这是我在线阅读的最好的拖放文章。

以下链接是拖放操作的一系列事件:

  1. 通过调用源代码管理的DoDragDrop方法启动拖动。 DoDragDrop方法有两个参数:

    data,指定要传递的数据

    allowedEffects,指定允许哪些操作(复制和/或移动) 将自动创建一个新的DataObject对象。

  2. 这又会引发GiveFeedback事件。在大多数情况下,您不必担心GiveFeedback事件,但如果您想在拖动过程中显示自定义鼠标指针,则可以在此处添加代码。

  3. AllowDrop属性设置为True的任何控件都是潜在的丢弃目标。 AllowDrop属性可以在设计时在“属性”窗口中设置,也可以在Form_Load事件中以编程方式设置。

  4. 当鼠标经过每个控件时,会引发该控件的DragEnter事件。 GetDataPresent方法用于确保数据格式适合目标控件,Effect属性用于显示相应的鼠标指针。

  5. 如果用户在有效的放置目标上释放鼠标按钮,则会引发DragDrop事件。 DragDrop事件处理程序中的代码从DataObject对象中提取数据并将其显示在目标控件中。

  6. 要检测源上的鼠标拖动操作,源代码管理需要订阅MouseLeftButtonDownMouseMove

    void Window1_Loaded(object sender, RoutedEventArgs e)
         {
             this.DragSource.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(DragSource_PreviewMouseLeftButtonDown);
             this.DragSource.PreviewMouseMove += new MouseEventHandler(DragSource_PreviewMouseMove);
         }
    

    防止开始误拖&amp;如果用户意外拖动操作,您可以使用SystemParameters.MinimumHorizontalDragDistanceSystemParameters.MinimumVerticalDragDistance

    void DragSource_PreviewMouseMove(object sender, MouseEventArgs e)
            {
                if (e.LeftButton == MouseButtonState.Pressed && !IsDragging)
                {
                    Point position = e.GetPosition(null);
    
                    if (Math.Abs(position.X - _startPoint.X) > SystemParameters.MinimumHorizontalDragDistance ||
    
                        Math.Abs(position.Y - _startPoint.Y) > SystemParameters.MinimumVerticalDragDistance)
    
                    {
                      StartDrag(e); 
                    }
                }
            }
    
            void DragSource_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
            {
                _startPoint = e.GetPosition(null);
            }
    

    现在你检测到一个拖动操作,你需要知道的只是落入。

    可以像这样做一个没有任何影响的简单场景。

    private void StartDrag(MouseEventArgs e)
            {
                IsDragging = true;
    
                DataObject data = new DataObject(System.Windows.DataFormats.Text.ToString(), "abcd");
    
                DragDropEffects de = DragDrop.DoDragDrop(this.DragSource, data, DragDropEffects.Move);
    
                IsDragging = false;
            }
    

    我认为这可以帮助你入门。我真的建议你阅读链接中的完整帖子。

    https://blogs.msdn.microsoft.com/jaimer/2007/07/12/drag-amp-drop-in-wpf-explained-end-to-end/