WPF中对鼠标事件转换为命令处理模式的鼠标位置参数传递及EventArgs传递

来源:互联网 发布:淘宝客的佣金一般多少 编辑:程序博客网 时间:2024/06/05 08:22

在WPF中使用命令模型,对于实现ICommandSource的元素来讲,比较方便,对于未实现ICommandSouce的元素来讲可以利用Blend中提供的行为来解决。通常情况下,命令对象可以传递命令参数(CommandParameter),如果将鼠标事件用命令来解决,则往往需要关注鼠标的位置,如果在事件处理方法中可以通过MouseEventArgs对象来获取。那如果在命令中获取鼠标位置呢,可能有多种解决方法,本文主要介绍一种利用Mouse.GetPosition(IInputElement)方法来获取鼠标相对于WPF元素的位置,以及利用Win32API 函数GetCursorPos()来获取屏幕鼠标位置的方法。

Xaml代码如下:

  <Window.Resources>
        <vm:MyViewModel x:Key="myViewModel"></vm:MyViewModel>
    </Window.Resources>
    <StackPanel DataContext="{StaticResource myViewModel}">
        <Label  Name="label" Content="my"/>
        <Canvas Name="canvas" Height="400"  MouseMove="btn_MouseMove" Background="AliceBlue">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="MouseDown">
                    <i:InvokeCommandAction Command="{Binding ShowMessageBoxCommand}" CommandParameter="{Binding ElementName=canvas}" />//将canvas作为参数传入,在viewmodel中通过Mouse.GetPosition(canvas)来获取鼠标位置

//说明:此处如果换成Prism库中的InvokeCommandAction,则可以直接将EventArgs对象属性或对象本身传递给Command,  例如在集合控件ListBox中写成<prism:InvokeCommandAction Command={Binding SelectedCommand}" TriggerParameterPath="AddedItems"/>,此处的AddedItems就是SelectionChangedEventArgs对象的属性,这样就可以把EventArgs对象属性传递给了命令,在viewModel中处理命令对象就可以很方便的获取到事件对象的属性。如果直接传递EventArs对象,则省略TriggerParameterPath属性或者将该属性写成TriggerParameterPath=""即可。(个人理解:做MVVM开发时,尽量不要将界面控件如Canvas或WPF事件对象EventArgs直接传递给ViewModel,这会造成ViewModel对象对界面控件类型的依赖,尽可能仅传递所用到的事件对象的参数即可)
                </i:EventTrigger>
                <i:EventTrigger EventName="MouseMove">
                    <i:InvokeCommandAction Command="{Binding ShowScreenMousePositionCommand}" CommandParameter="{Binding ElementName=label}" />
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Canvas>
    </StackPanel>

在ViewModel中的代码如下:

    public class MyViewModel:BindableBase
    { 

      private string _myProperty = "";
        public string MyProperty { get { return _myProperty; } set { SetProperty(ref _myProperty, value);
                RaisePropertyChanged();
            } }
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern bool GetCursorPos(out POINT pt);
        public struct POINT
        {
            public int X;
            public int Y;
            public POINT(int x, int y)
            {
                this.X = x;
                this.Y = y;
            }
        }
        public ICommand ShowMessageBoxCommand
        {
            get
            {
                return new DelegateCommand<Canvas>((c) => {   //DelegateCommand<T>来自于Prism框架
                    Point p = Mouse.GetPosition(c);
                    MessageBox.Show($"x={p.X},y={p.Y}"); //显示鼠标在Canvas上的位置
                });
            }
        }
        public ICommand ShowScreenMousePositionCommand
        {
            get
            {
                return new DelegateCommand<Label>((c) => {
                    POINT p = new POINT();  //利用自定义的POINT结构体,参数类型为整数。
                                            //注:System.Windows.Point结构体的参数是浮点
                    GetCursorPos(out p);//利用win32API获取鼠标在显示屏上的位置
                    c.Content = string.Format("{0},{1}", p.X, p.Y);
                });
            }
        }
    }

}

原创粉丝点击