WPF / Caliburn Micro中的鼠标处理程序

时间:2013-07-01 22:35:38

标签: wpf mouseevent caliburn.micro

我认为这是一个简单的情况,但似乎无法弄清楚如何完成它。我是WPF和Caliburn Micro框架的新手。在我的视图中,我有一个画布,在这个画布上我有一个图像。我想编写一些鼠标事件处理程序(MouseLeftButtonDown,MouseLeftButtonUp和MouseMove),当光标在Image中时调用它们。我已经成功地在ViewModel中创建了事件处理程序,但我似乎无法弄清楚如何在处理程序中获取当前游标位置。 MouseEventArgs.GetPosition需要一个IInputElement作为参数......不知道如何获得它。

这是我的XAML(视图):

<Canvas x:Name="ImageCanvas" >    
    <Image Source="{Binding DataImage}" 
           x:Name="ContainerImage"
              cal:Message.Attach=
              "[Event MouseLeftButtonDown] = [Action MouseDown_Image($source, $eventArgs)];
               [Event MouseLeftButtonUp] = [Action MouseUp_Image($source, $eventArgs)];
               [Event MouseMove] = [Action MouseMove_Image($source, $eventArgs)]">
    </Image>
</Canvas>

这是我的C#(viewmodel)

public void MouseDown_Image(object sender, MouseEventArgs e)
    {
      // How do I get cursor position here??

      // convert to Image coordinates??
    }

public void MouseUp_Image(object sender, MouseEventArgs e)
    {
      // How do I get cursor position here??

      // convert to Image coordinates??
    }

public void MouseMove_Image(object sender, MouseEventArgs e)
    {
      // How do I get cursor position here??

      // convert to Image coordinates??
    }

一旦我这样做,我需要将鼠标坐标转换为图像上的坐标......但首先要做的事情。

谢谢!

2 个答案:

答案 0 :(得分:6)

创建SpecialValues字典条目以处理图像的坐标可能很有用 - 这样您就可以在中心位置添加功能,或者甚至只在图像中的X / Y位置或另一个缩放输入控件:

e.g。在你的CM Bootstrapper配置:

            MessageBinder.SpecialValues.Add("$scaledmousex", (ctx) =>
            {
                var img = ctx.Source as Image;
                var input = ctx.Source as IInputElement;
                var e = ctx.EventArgs as MouseEventArgs;

                // If there is an image control, get the scaled position
                if (img != null && e != null)
                {
                    Point position = e.GetPosition(img);
                    return (int)(img.Source.Width * (position.X / img.ActualWidth));
                }

                // If there is another type of of IInputControl get the non-scaled position - or do some processing to get a scaled position, whatever needs to happen
                if (e != null && input != null)
                    return e.GetPosition(input).X;

                // Return 0 if no processing could be done
                return 0;
            });

此字典用于解析操作消息绑定中的输入参数,并将运行上述匿名委托,返回您指定的值(您还需要添加$scaledmousey

然后在绑定中使用此值:

cal:Message.Attach="[Event MouseMove] = [Action MouseMove_Image($scaledmousex, $scaledmousey)]"

这样,如果您决定要更改源类型,您仍然可以在没有太多/任何重构的情况下获得该位置,并且您的代码将通过中央处理路径

这也确保了view / viewmodel被解耦 - MVVM模式的一部分目标

答案 1 :(得分:0)

我相信我已经解决了!

在我的XAML中,我将事件处理程序附加到Image对象上的事件。因此,我的事件处理程序中的发件人可以强制转换为Image类型。然后,您可以将发件人作为参数传递给GetPosition。

另外,我能够将发送的坐标转换为实际图像坐标。知道原始图像的像素大小,它只是一些简单的缩放数学。

以下是我的一个鼠标处理程序的代码:

public void MouseDown_Image(object sender, MouseEventArgs e)
   {

      // Get the x and y coordinates of the mouse pointer.
       System.Windows.Point position = e.GetPosition((Image)sender);
       int pX = (int)position.X;
       int pY = (int)position.Y;

     // DataImage is the actual Image object that is being shown in the view
       int X_ImageCoordinates = (int)(DataImage.PixelWidth * (position.X/img.ActualWidth));
       int Y_ImageCoordinates = (int)(DataImage.PixelHeight * (position.Y / img.ActualHeight));                
    }

原来很简单!应该如此。

如果有更好的解决方案,或者由于某种原因我犯了错误,请告诉我。

谢谢!