C# - WPF - 画布上的 Mousemove 事件将使鼠标事件过载,因此不会触发单击事件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27075815/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 12:43:19  来源:igfitidea点击:

C# - WPF - Mousemove event on canvas will overload the mouse events so click event is not fired

c#wpfcanvasmouseevent

提问by NoNameProvided

I use Shapes and Canvas, I want to make something like a mapeditor. When the mouse move over the canvas I draw the actually selected object to the canvas at the mouse position on every move, so who use the program can see how it will look like if the object is placed there.

我使用 Shapes 和 Canvas,我想做一个类似地图编辑器的东西。当鼠标在画布上移动时,我会在每次移动鼠标位置时将实际选择的对象绘制到画布上,因此使用该程序的人可以看到如果将对象放置在那里会是什么样子。

And on mouse click I add the current object/position to a list, which contains the placed elements which need to be drawn on the canvas in every update.

在鼠标单击时,我将当前对象/位置添加到列表中,该列表包含每次更新时需要在画布上绘制的放置元素。

The problem is if the mouse move handler is active (binded to canvas) then the click event is not fired alway, I need to click continuously For about ten clicks to place the element. If the mouse move event is not binded then the click works perfectly.

问题是,如果鼠标移动处理程序处于活动状态(绑定到画布),则不会始终触发单击事件,我需要连续单击大约十次单击以放置元素。如果鼠标移动事件未绑定,则单击工作正常。

I made a GIF to demonstrate my problem.

我制作了一个 GIF 来演示我的问题。

Here is when the mouse move event is used

这是使用鼠标移动事件的时间

and here is when not

这是什么时候不

I think it's because the move event oveload the event handling, and there is no resource to run the click event.

我认为这是因为移动事件超载了事件处理,并且没有资源来运行点击事件。

How I could use the two event together?

我怎么能一起使用这两个事件?

EDIT

编辑

As advised, I attach some code to the example.

按照建议,我在示例中附加了一些代码。

I have a model for the canvas named mapEditorModel. The property which is important to us is the mapEditorModel.MapObjectswhich is a list containing the elements need to be drawed to the canvas.

我有一个名为mapEditorModel. 对我们来说很重要的属性是mapEditorModel.MapObjects包含需要绘制到画布的元素的列表。

The list contains a wrapper object, its contains a lot of information about the elment, which is important to us is that it contains the prebuild shape for draw.

该列表包含一个包装对象,它包含很多关于元素的信息,对我们来说重要的是它包含用于绘制的预构建形状。

I have a function which is draw the elments on the canvas:

我有一个在画布上绘制元素的函数:

private void DrawElementOnCanvas(MapElementContainer item)
    {
        Rectangle shape = item.Shape;

        CanvasElement.Children.Add(shape);
        Canvas.SetLeft(shape, item.Position.X);
        Canvas.SetTop(shape, item.Position.Y);    
    }

And I have an updateCanvas()method like this:

我有一个updateCanvas()这样的方法:

private void updateCanvas()
    {
        CanvasElement.Children.RemoveRange(0, CanvasElement.Children.Count);

        foreach (MapElementContainer item in mapEditorModel.MapObjects)
        {
            DrawElementOnCanvas(item);   
        }
        //CollisionDetection();
    }

And the two event method is:

两个事件方法是:

private void CanvasElement_MouseMove(object sender, MouseEventArgs e)
    {
        updateCanvas();

        MapElementContainer mapObject = new MapElementContainer();

        mapObject.Position = e.GetPosition((Canvas)sender);
        mapObject.MapElement = new ContainerMapObject();
        mapObject.CurrentRotateDegree = mapEditorModel.CurrentRotateDegree;
        mapObject.Shape = BuildShape(mapObject);

        DrawElementOnCanvas(mapObject);   
    }

private void CanvasElement_MouseDown(object sender, MouseButtonEventArgs e)
    {
        MapElementContainer mapObject = new MapElementContainer();

        mapObject.Position = e.GetPosition((Canvas)sender);
        mapObject.MapElement = new ContainerMapObject();
        mapObject.CurrentRotateDegree = mapEditorModel.CurrentRotateDegree;
        mapObject.Shape = BuildShape(mapObject);

        mapEditorModel.MapObjects.Add(mapObject);

        updateCanvas();
    }

EDIT 2

编辑 2

If I comment all the code in the mouse move function, then I still can't place any element on the canvas at the first click, so maybe is it by design?

如果我注释掉鼠标移动函数中的所有代码,那么我仍然无法在第一次单击时在画布上放置任何元素,所以也许是设计使然?

采纳答案by stijn

Here's a minimal code sample which works properly and does not have the problem you mention: it can add shapes as fast as I can click. I suggest you inspect the differences with your code to find the culprit - for one, I don't continuously call updateCanvas or similar as this is not needed.

这是一个最小的代码示例,它可以正常工作并且没有你提到的问题:它可以像我点击一样快地添加形状。我建议您检查代码的差异以找到罪魁祸首 - 首先,我不会不断调用 updateCanvas 或类似方法,因为这不是必需的。

xaml:

xml:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" SizeToContent="WidthAndHeight">
  <Canvas x:Name="canvas" Background="AntiqueWhite" Width="1024" Height="768"
          MouseMove="Canvas_MouseMove" MouseDown="Canvas_MouseDown" />
</Window>

xaml.cs:

xaml.cs:

using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;

namespace WpfApplication1
{
  public class Item
  {
    private readonly Rectangle shape;

    public Item( Canvas canvas )
    {
      shape = new Rectangle { Width = 50, Height = 50, Fill = Brushes.Black };
      canvas.Children.Add( shape );
      SetPosition( 0.0, 0.0 );
    }

    public void SetPosition( double x, double y )
    {
      Canvas.SetLeft( shape, x );
      Canvas.SetTop( shape, y );
    }
  }

  public partial class MainWindow : Window
  {
    private readonly IList<Item> shapes;
    private Item currentMovingShape;

    public MainWindow()
    {
      InitializeComponent();
      shapes = new List<Item>();
      InitMovingShape();
    }

    private void InitMovingShape()
    {
      currentMovingShape = new Item( canvas );
    }

    private void SetMovingShapePosition( MouseEventArgs e )
    {
      var pos = e.GetPosition( canvas );
      currentMovingShape.SetPosition( pos.X, pos.Y );
    }

    private void Canvas_MouseMove( object sender, MouseEventArgs e )
    {
      SetMovingShapePosition( e );
    }

    private void Canvas_MouseDown( object sender, MouseButtonEventArgs e )
    {
      shapes.Add( currentMovingShape );
      InitMovingShape();
      SetMovingShapePosition( e );
    }
  }
}

回答by bernd_rausch

Perhaps the MouseDown event is handled in the MapElementContainer class and never reaches CanvasElement? In your second video you always clicked on an empty space. In your first video there is always the MapElementContainer under the mouse.

也许 MouseDown 事件是在 MapElementContainer 类中处理的,并且永远不会到达 CanvasElement?在您的第二个视频中,您总是点击空白区域。在您的第一个视频中,鼠标下方总是有 MapElementContainer。