Handling Mouse Events in MVVM in WPF
Asked Answered
B

3

9

I am Using MVVM with WPF. i am halted in a way, i want your views about this. i am firing Mouse Events using MouseBehaviour.cs class , Is there any other way to handle Mouse Events in MVVM WPF

using System.Windows;
using System.Windows.Input;

namespace Lovatts.MouseBehaviours
{
    public class MouseBehaviour
    {
        #region MouseUp

        public static readonly DependencyProperty MouseUpCommandProperty =
            DependencyProperty.RegisterAttached("MouseUpCommand", typeof(ICommand), typeof(MouseBehaviour), new FrameworkPropertyMetadata(new PropertyChangedCallback(MouseUpCommandChanged)));

        private static void MouseUpCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)d;

            element.MouseUp += element_MouseUp;
        }

        static void element_MouseUp(object sender, MouseButtonEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)sender;

            ICommand command = GetMouseUpCommand(element);

            command.Execute(e);
        }



        public static void SetMouseUpCommand(UIElement element, ICommand value)
        {
            element.SetValue(MouseUpCommandProperty, value);
        }

        public static ICommand GetMouseUpCommand(UIElement element)
        {
            return (ICommand)element.GetValue(MouseUpCommandProperty);
        }

        #endregion

        #region MouseDown

        public static readonly DependencyProperty MouseDownCommandProperty =
            DependencyProperty.RegisterAttached("MouseDownCommand", typeof(ICommand), typeof(MouseBehaviour), new FrameworkPropertyMetadata(new PropertyChangedCallback(MouseDownCommandChanged)));

        private static void MouseDownCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)d;

            element.MouseDown += element_MouseDown;
        }

        static void element_MouseDown(object sender, MouseButtonEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)sender;

            ICommand command = GetMouseDownCommand(element);

            command.Execute(e);
        }

        public static void SetMouseDownCommand(UIElement element, ICommand value)
        {
            element.SetValue(MouseDownCommandProperty, value);
        }

        public static ICommand GetMouseDownCommand(UIElement element)
        {
            return (ICommand)element.GetValue(MouseDownCommandProperty);
        }

        #endregion

        #region MouseLeave

        public static readonly DependencyProperty MouseLeaveCommandProperty =
            DependencyProperty.RegisterAttached("MouseLeaveCommand", typeof(ICommand), typeof(MouseBehaviour), new FrameworkPropertyMetadata(new PropertyChangedCallback(MouseLeaveCommandChanged)));

        private static void MouseLeaveCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)d;

            element.MouseLeave += new MouseEventHandler(element_MouseLeave);
        }

        static void element_MouseLeave(object sender, MouseEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)sender;

            ICommand command = GetMouseLeaveCommand(element);

            command.Execute(e);
        }

        public static void SetMouseLeaveCommand(UIElement element, ICommand value)
        {
            element.SetValue(MouseLeaveCommandProperty, value);
        }

        public static ICommand GetMouseLeaveCommand(UIElement element)
        {
            return (ICommand)element.GetValue(MouseLeaveCommandProperty);
        }
        #endregion

        #region MouseLeftButtonDown

        public static readonly DependencyProperty MouseLeftButtonDownCommandProperty =
            DependencyProperty.RegisterAttached("MouseLeftButtonDownCommand", typeof(ICommand), typeof(MouseBehaviour), new FrameworkPropertyMetadata(new PropertyChangedCallback(MouseLeftButtonDownCommandChanged)));

        private static void MouseLeftButtonDownCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)d;

            element.MouseLeftButtonDown += element_MouseLeftButtonDown;
        }

        static void element_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)sender;

            ICommand command = GetMouseLeftButtonDownCommand(element);

            command.Execute(e);
        }

        public static void SetMouseLeftButtonDownCommand(UIElement element, ICommand value)
        {
            element.SetValue(MouseLeftButtonDownCommandProperty, value);
        }

        public static ICommand GetMouseLeftButtonDownCommand(UIElement element)
        {
            return (ICommand)element.GetValue(MouseLeftButtonDownCommandProperty);
        }

        #endregion

        #region MouseLeftButtonUp

        public static readonly DependencyProperty MouseLeftButtonUpCommandProperty =
            DependencyProperty.RegisterAttached("MouseLeftButtonUpCommand", typeof(ICommand), typeof(MouseBehaviour), new FrameworkPropertyMetadata(new PropertyChangedCallback(MouseLeftButtonUpCommandChanged)));

        private static void MouseLeftButtonUpCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)d;

            element.MouseLeftButtonUp += element_MouseLeftButtonUp;
        }

        static void element_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)sender;

            ICommand command = GetMouseLeftButtonUpCommand(element);

            command.Execute(e);
        }

        public static void SetMouseLeftButtonUpCommand(UIElement element, ICommand value)
        {
            element.SetValue(MouseLeftButtonUpCommandProperty, value);
        }

        public static ICommand GetMouseLeftButtonUpCommand(UIElement element)
        {
            return (ICommand)element.GetValue(MouseLeftButtonUpCommandProperty);
        }

        #endregion

        #region MouseMove

        public static readonly DependencyProperty MouseMoveCommandProperty =
            DependencyProperty.RegisterAttached("MouseMoveCommand", typeof(ICommand), typeof(MouseBehaviour), new FrameworkPropertyMetadata(new PropertyChangedCallback(MouseMoveCommandChanged)));

        private static void MouseMoveCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)d;

            element.MouseMove += new MouseEventHandler(element_MouseMove);
        }

        static void element_MouseMove(object sender, MouseEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)sender;

            ICommand command = GetMouseMoveCommand(element);

            command.Execute(e);
        }

        public static void SetMouseMoveCommand(UIElement element, ICommand value)
        {
            element.SetValue(MouseMoveCommandProperty, value);
        }

        public static ICommand GetMouseMoveCommand(UIElement element)
        {
            return (ICommand)element.GetValue(MouseMoveCommandProperty);
        }

        #endregion

        #region MouseRightButtonDown

        public static readonly DependencyProperty MouseRightButtonDownCommandProperty =
            DependencyProperty.RegisterAttached("MouseRightButtonDownCommand", typeof(ICommand), typeof(MouseBehaviour), new FrameworkPropertyMetadata(new PropertyChangedCallback(MouseRightButtonDownCommandChanged)));

        private static void MouseRightButtonDownCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)d;

            element.MouseRightButtonDown += element_MouseRightButtonDown;
        }

        static void element_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)sender;

            ICommand command = GetMouseRightButtonDownCommand(element);

            command.Execute(e);
        }

        public static void SetMouseRightButtonDownCommand(UIElement element, ICommand value)
        {
            element.SetValue(MouseRightButtonDownCommandProperty, value);
        }

        public static ICommand GetMouseRightButtonDownCommand(UIElement element)
        {
            return (ICommand)element.GetValue(MouseRightButtonDownCommandProperty);
        }

        #endregion

        #region MouseRightButtonUp

        public static readonly DependencyProperty MouseRightButtonUpCommandProperty =
            DependencyProperty.RegisterAttached("MouseRightButtonUpCommand", typeof(ICommand), typeof(MouseBehaviour), new FrameworkPropertyMetadata(new PropertyChangedCallback(MouseRightButtonUpCommandChanged)));

        private static void MouseRightButtonUpCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)d;

            element.MouseRightButtonUp += element_MouseRightButtonUp;
        }

        static void element_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)sender;

            ICommand command = GetMouseRightButtonUpCommand(element);

            command.Execute(e);
        }

        public static void SetMouseRightButtonUpCommand(UIElement element, ICommand value)
        {
            element.SetValue(MouseRightButtonUpCommandProperty, value);
        }

        public static ICommand GetMouseRightButtonUpCommand(UIElement element)
        {
            return (ICommand)element.GetValue(MouseRightButtonUpCommandProperty);
        }

        #endregion

        #region MouseWheel

        public static readonly DependencyProperty MouseWheelCommandProperty =
            DependencyProperty.RegisterAttached("MouseWheelCommand", typeof(ICommand), typeof(MouseBehaviour), new FrameworkPropertyMetadata(new PropertyChangedCallback(MouseWheelCommandChanged)));

        private static void MouseWheelCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)d;

            element.MouseWheel += new MouseWheelEventHandler(element_MouseWheel);
        }

        static void element_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)sender;

            ICommand command = GetMouseWheelCommand(element);

            command.Execute(e);
        }

        public static void SetMouseWheelCommand(UIElement element, ICommand value)
        {
            element.SetValue(MouseWheelCommandProperty, value);
        }

        public static ICommand GetMouseWheelCommand(UIElement element)
        {
            return (ICommand)element.GetValue(MouseWheelCommandProperty);
        }

        #endregion
    }
}

Here is my Xaml Code

<Window x:Class="Lovatts.MouseBehaviours.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:MouseBehaviours="clr-namespace:Lovatts.MouseBehaviours" x:Name="RibbonWindow"
        Width="640" Height="480" DataContext="{Binding Main, Source={StaticResource Locator}}">
    <Grid>
        <Rectangle Width="100" Height="100" Fill="Blue" MouseBehaviours:MouseBehaviour.MouseUpCommand="{Binding MouseUpCommand}">
    </Rectangle>
    <Rectangle Width="100" Height="100" x:Name="Rectangle" Fill="Red" MouseBehaviours:MouseBehaviour.MouseUpCommand="{Binding MouseUpCommand}" Margin="75,109,457,241">
    </Rectangle>
    </Grid>
</Window>

MainViewModel.cs

using System.Windows.Input;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Windows;

namespace MouseBehaviours.ViewModel
{
    public class MainViewModel : ViewModelBase
    {
         private RelayCommand _mouseUpCommand;
        public RelayCommand MouseUpCommand
        {
            get
            {
                if (_mouseUpCommand == null) return _mouseUpCommand = new RelayCommand(param => ExecuteMouseUp((MouseEventArgs)param));
                return _mouseUpCommand;
            }
            set { _mouseUpCommand = value; }
        }

        private void ExecuteMouseUp(MouseEventArgs e)
        {
            Console.WriteLine("Mouse Up : " + e.GetPosition((IInputElement)e.Source));
        }
    }

    public class RelayCommand : ICommand
    {
        #region Fields

        private readonly Action<object> _execute;
        private readonly Predicate<object> _canExecute;
        private string _displayText;

        public static List<string> Log = new List<string>();
        private Action<object> action;

        #endregion // Fields

        #region Constructors

        /// <summary>
        /// Creates a new command that can always execute.
        /// </summary>
        /// <param name="execute">The execution logic.</param>
        public RelayCommand(Action<object> execute)
            : this(execute, null)
        {
        }

        /// <summary>
        /// Creates a new command.
        /// </summary>
        /// <param name="execute">The execution logic.</param>
        /// <param name="canExecute">The execution status logic.</param>
        public RelayCommand(Action<object> execute, Predicate<object> canExecute)
            : this(execute, canExecute, "")
        {
        }

        public RelayCommand(Action<object> execute, Predicate<object> canExecute, string displayText)
        {
            if (execute == null)
                throw new ArgumentNullException("execute");

            _execute = execute;
            _canExecute = canExecute;
            _displayText = displayText;
        }


        public string DisplayText
        {
            get { return _displayText; }
            set { _displayText = value; }
        }

        #endregion // Constructors

        #region ICommand Members

        [DebuggerStepThrough]
        public bool CanExecute(object parameter)
        {
            return _canExecute == null ? true : _canExecute(parameter);
        }

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        public void Execute(object parameter)
        {

            _execute(parameter);
        }

        #endregion // ICommand Members
    }
        //class MainViewModel
        //{
        //}
    }
Boaz answered 17/6, 2014 at 10:2 Comment(2)
you can use interactivity to call your command on any event. Heres the example c-sharpcorner.com/Blogs/11789/…Duotone
@Harjeet Thanks for sharing your codes. I tried to implement the structure presented in the question. But in the XAML when I use MouseBehaviours:MouseBehaviour.MouseUpCommand="{Binding MouseUpCommand} in the Binding section it doesn't recognize MouseUpCommand in the binding part. Do you know what I am missing? I appreciate your response.Warila
G
2

@harjeet you need to use the below structure for Image MouseUp i.e instead of using "Image" try to use "Hyperlink command property" in TextBlock:

<TextBlock Panel.ZIndex="990"
       Canvas.Right="30"
       Canvas.Left="498"
       Canvas.Top="4">
  <Hyperlink TextDecorations="None"
         Command="{Binding CloseLoginSettingPopup}">  
  <Image  Cursor="Hand"
        x:Name="Pop2"
        Source="/img/close1.png"
        Height="40"
        Width="40"
        Panel.ZIndex="990"
        Canvas.Right="30"
        Canvas.Left="498"
        Canvas.Top="4" />
  </Hyperlink>
</TextBlock>
Godden answered 17/6, 2014 at 12:33 Comment(0)
D
16

Instead of writing you own behavior and calling commands from it, you can leverage the EventTriggers and Interactivity to bind the event action to the command.

here is simple example of doing it

http://www.c-sharpcorner.com/Blogs/11789/example-of-eventtrigger-in-mvvm-application.aspx

as described in the example if you want to fire command on MouseUp event on your rectangle you can just do:

<Rectangle >
  <i:Interaction.Triggers>
    <i:EventTrigger EventName="MouseUp">
      <i:InvokeCommandAction Command="{Binding MyCommand}"/>
    </i:EventTrigger>
  </i:Interaction.Triggers>
</Rectangle >
Duotone answered 17/6, 2014 at 10:53 Comment(3)
Slight issue here in that most InvokeCommandAction's don't pass in the event args, this means you can detect the event but not the circumstances, so you are probably not much better off than using inputbindingsHighboy
@Highboy I tried to implement the structure presented in the question. But in the XAML when I use MouseBehaviours:MouseBehaviour.MouseUpCommand="{Binding MouseUpCommand} in the Binding section it doesn't recognize MouseUpCommand in the binding part. Do you know what I am missing? I appreciate your response.Warila
@Warila hard to say from just a snippet embedded in a comment would suggest asking a question of your own and providing a full example of the problemHighboy
G
2

@harjeet you need to use the below structure for Image MouseUp i.e instead of using "Image" try to use "Hyperlink command property" in TextBlock:

<TextBlock Panel.ZIndex="990"
       Canvas.Right="30"
       Canvas.Left="498"
       Canvas.Top="4">
  <Hyperlink TextDecorations="None"
         Command="{Binding CloseLoginSettingPopup}">  
  <Image  Cursor="Hand"
        x:Name="Pop2"
        Source="/img/close1.png"
        Height="40"
        Width="40"
        Panel.ZIndex="990"
        Canvas.Right="30"
        Canvas.Left="498"
        Canvas.Top="4" />
  </Hyperlink>
</TextBlock>
Godden answered 17/6, 2014 at 12:33 Comment(0)
W
-1

https://learn.microsoft.com/en-us/dotnet/api/system.windows.input.mouseaction

<Rectangle>
    <Rectangle.InputBindings>
        <MouseBinding MouseAction="LeftClick" Command="{Binding MyCommand}" />
    </Rectangle.InputBindings>
</Rectangle>
Weirdie answered 21/11, 2022 at 23:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.