Reputation: 8987
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.
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.
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.MapObjects
which is a list containing the elements need to be drawed to the canvas.
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:
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
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?
Upvotes: 5
Views: 9281
Reputation: 35901
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.
xaml:
<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:
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 );
}
}
}
Upvotes: 2
Reputation: 335
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.
Upvotes: 0