简体   繁体   中英

How to get mouse position when using XamlBehaviorsWpf and MVVM (Formerly Interactivity)

Now that XamlBehaviorsWpf [Tag missing, but I don't have the rights to add] has replaced System.Windows.Interactivity in Blend SDK which is deprecated I'm struggling to figure out how to use it to get Mouse position on a canvas.

MouseX and MouseY below I think is the old Interactivity Syntax but I can't seem to find a XamlBehaviorsWpf equivalent. As such, using these properties creates a compile error.

The Click method is working and returns the coordinates at their default 999,999 value.

Does anyone know how I can get the current mouse position using XamlBehaviorsWpf ?

XAML:

        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas  Height="800" Background="Black">
                    <behaviors:Interaction.Triggers>
                        <behaviors:EventTrigger EventName="MouseLeftButtonDown">
                            <behaviors:CallMethodAction TargetObject="{Binding}" MethodName="Click"/>
                        </behaviors:EventTrigger>
                        <behaviors:EventTrigger EventName="MouseMove">
                            <behaviors:ChangePropertyAction MouseX="{Binding X, Mode=OneWayToSource}"/>
                            <behaviors:ChangePropertyAction MouseY="{Binding Y, Mode=OneWayToSource}"/>
                        </behaviors:EventTrigger>
                    </behaviors:Interaction.Triggers>
                </Canvas>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>

ViewModel

    public void Click(object sender, MouseButtonEventArgs e)
    {
        MessageBox.Show(X.ToString() + ","+ Y.ToString());
    }

    private double x = 999;

    public double X
    {
        get { return x; }
        set { SetAndNotify(ref this.x, value); }
    }

    private double y = 999;

    public double Y
    {
        get { return y; }
        set { SetAndNotify(ref this.y, value); }
    }

I lot of my issues seemed to stem from a typo, which been corrected in the question (thanks Andy). There's an easy to follow article here that I used to get it working. You can basically swap all System.Windows.Interactivity references with XamlBehaviorsWpf and it will work all the same.

My working code below for easy reference or if the link above dissapears:

XAML

<UserControl x:Class="Drain.Views.Cad.CadView"
             x:Name="cad"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:behaviors="http://schemas.microsoft.com/xaml/behaviors"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:Drain.Views.Cad"
             xmlns:vm="clr-namespace:Drain.ViewModels.Cad"
             xmlns:cad="clr-namespace:Drain.Models.Cad"
             xmlns:s="https://github.com/canton7/Stylet"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        
        
        <behaviors:Interaction.Behaviors>
            <behaviors:FluidMoveBehavior AppliesTo="Children" />
        </behaviors:Interaction.Behaviors>
        
        <ItemsControl x:Name="MainPanel">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <Canvas  Height="800" Background="Black">
                        <behaviors:Interaction.Triggers>
                            <behaviors:EventTrigger EventName="MouseLeftButtonDown">
                                <behaviors:CallMethodAction TargetObject="{Binding}" MethodName="Click"/>
                            </behaviors:EventTrigger>
                        </behaviors:Interaction.Triggers>
                        <behaviors:Interaction.Behaviors>
                            <vm:MouseBehaviour MouseX="{Binding X, Mode=OneWayToSource}"
                                               MouseY="{Binding Y, Mode=OneWayToSource}" />
                        </behaviors:Interaction.Behaviors>
                    </Canvas>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemContainerStyle>
                <Style>
                    <Setter Property="Canvas.Left" Value="{Binding Path=X, Mode=OneWay}" />
                    <Setter Property="Canvas.Top" Value="{Binding Path=Y, Mode=OneWay}" />
                </Style>
            </ItemsControl.ItemContainerStyle>
        </ItemsControl>
    </Grid>
</UserControl>

VIEWMODEL

    public void Click(object sender, MouseButtonEventArgs e)
    {
        MessageBox.Show(X.ToString() + ","+ Y.ToString());
    }

    private double x = 999;

    public double X
    {
        get { return x; }
        set { SetAndNotify(ref this.x, value); }
    }

    private double y = 999;

    public double Y
    {
        get { return y; }
        set { SetAndNotify(ref this.y, value); }
    }

MouseBehaviour Class

using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using Microsoft.Xaml.Behaviors;

namespace Drain.ViewModels.Cad
{
   public class MouseBehaviour : Behavior<Panel>
    {
        public static readonly DependencyProperty MouseYProperty = DependencyProperty.Register(
           "MouseY", typeof(double), typeof(MouseBehaviour), new PropertyMetadata(default(double)));

        public static readonly DependencyProperty MouseXProperty = DependencyProperty.Register(
           "MouseX", typeof(double), typeof(MouseBehaviour), new PropertyMetadata(default(double)));

        public double MouseY
        {
            get { return (double)GetValue(MouseYProperty); }
            set { SetValue(MouseYProperty, value); }
        }

        public double MouseX
        {
            get { return (double)GetValue(MouseXProperty); }
            set { SetValue(MouseXProperty, value); }
        }

        protected override void OnAttached()
        {
            AssociatedObject.MouseMove += AssociatedObjectOnMouseMove;
        }

        private void AssociatedObjectOnMouseMove(object sender, MouseEventArgs mouseEventArgs)
        {
            var pos = mouseEventArgs.GetPosition(AssociatedObject);
            MouseX = pos.X;
            MouseY = pos.Y;
        }

        protected override void OnDetaching()
        {
            AssociatedObject.MouseMove -= AssociatedObjectOnMouseMove;
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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