wpf window mousedown implemented in mvvm as command via behavior
public static class MouseBehavior { public static readonly DependencyProperty MouseDownCommandProperty = DependencyProperty.RegisterAttached("MouseDownCommand", typeof(ICommand), typeof(MouseBehavior), new PropertyMetadata(null, OnMouseDownCommandChanged)); public static void SetMouseDownCommand(DependencyObject dObj, ICommand commandValue) { dObj.SetValue(MouseDownCommandProperty, commandValue); } public static ICommand GetMouseDownCommand(DependencyObject dObj) { return (ICommand)dObj.GetValue(MouseDownCommandProperty); } private static void OnMouseDownCommandChanged(DependencyObject dObj, DependencyPropertyChangedEventArgs e) { if (dObj is UIElement element) { if (e.NewValue != null) { element.MouseDown += Element_MouseDown; } else { element.MouseDown -= Element_MouseDown; } } } private static void Element_MouseDown(object sender, MouseButtonEventArgs e) { var element = sender as UIElement; if (element != null) { var command = GetMouseDownCommand(element); if (command?.CanExecute(e) == true) { command.Execute(e); } } } } <Window x:Class="WpfApp202.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp202" xmlns:behavior="http://schemas.microsoft.com/xaml/behaviors" mc:Ignorable="d" WindowState="Maximized" Title="MainWindow" Height="450" Width="800" local:MouseBehavior.MouseDownCommand="{Binding WindowMouseDownCommand}"> <Grid> </Grid> </Window> //vm public DelCommand WindowMouseDownCommand { get; set; } WindowMouseDownCommand = new DelCommand(MouseDownCommandExecuted, MouseDownCommandCanExecute); private bool MouseDownCommandCanExecute(object? obj) { return true; } private int itemsCount = 0; private int idx = 0; private void MouseDownCommandExecuted(object? obj) { if (obj != null && obj is MouseEventArgs e) { var pos = e.GetPosition(null); string str = $"{++idx},X:{pos.X},Y:{pos.Y}"; PosStrList.Add(str); itemsCount = PosStrList.Count; SelectedItem = PosStrList[itemsCount - 1]; } }
//xaml <Window x:Class="WpfApp202.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp202" xmlns:behavior="http://schemas.microsoft.com/xaml/behaviors" mc:Ignorable="d" WindowState="Maximized" Title="{Binding SelectedItem,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Height="450" Width="800" local:MouseBehavior.MouseDownCommand="{Binding WindowMouseDownCommand}"> <Grid> <ListBox Width="500" HorizontalAlignment="Left" VerticalAlignment="Stretch" SelectedItem="{Binding SelectedItem,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" ItemsSource="{Binding PosStrList,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"> <behavior:Interaction.Triggers> <behavior:EventTrigger EventName="SelectionChanged"> <behavior:InvokeCommandAction Command="{Binding SelectionChangedCommand}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBox}}}"/> </behavior:EventTrigger> </behavior:Interaction.Triggers> <ListBox.ItemContainerStyle> <Style TargetType="{x:Type ListBoxItem}"> <Setter Property="FontSize" Value="20"/> <Style.Triggers> <Trigger Property="IsSelected" Value="True"> <Setter Property="FontSize" Value="50"/> <Setter Property="Foreground" Value="Red"/> </Trigger> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="FontSize" Value="50"/> <Setter Property="Foreground" Value="Blue"/> </Trigger> </Style.Triggers> </Style> </ListBox.ItemContainerStyle> </ListBox> </Grid> </Window> //cs using System.Collections.ObjectModel; using System.ComponentModel; using System.Runtime.CompilerServices; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace WpfApp202 { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); var vm = new MainVM(); this.DataContext = vm; } private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { } } public class MainVM : INotifyPropertyChanged { public MainVM() { PosStrList = new ObservableCollection<string>(); WindowMouseDownCommand = new DelCommand(MouseDownCommandExecuted, MouseDownCommandCanExecute); SelectionChangedCommand = new DelCommand(SelectionChangedCommandExecuted, SelectionChangedCommandCanExecute); } private bool SelectionChangedCommandCanExecute(object? obj) { return true; } private void SelectionChangedCommandExecuted(object? obj) { if(obj!=null) { Application.Current?.Dispatcher.BeginInvoke(new Action(() => { var lbx = obj as ListBox; if (lbx != null) { lbx.ScrollIntoView(lbx.Items[itemsCount - 1]); } })); } } public DelCommand WindowMouseDownCommand { get; set; } public DelCommand SelectionChangedCommand { get; set; } public event PropertyChangedEventHandler? PropertyChanged; private void OnPropertyChanged([CallerMemberName] string propName = "") { var handler = PropertyChanged; if (handler != null) { handler?.Invoke(this, new PropertyChangedEventArgs(propName)); } } private string selectedItem; public string SelectedItem { get { return selectedItem; } set { if (value != selectedItem) { selectedItem = value; OnPropertyChanged(nameof(SelectedItem)); } } } private ObservableCollection<string> posStrList; public ObservableCollection<string> PosStrList { get { return posStrList; } set { if (value != posStrList) { posStrList = value; OnPropertyChanged(nameof(PosStrList)); } } } //private ICommand mouseDownCommand; //public ICommand MouseUpCommand //{ // get // { // if(mouseDownCommand == null) // { // mouseDownCommand = new DelCommand(MouseUpCommandExecuted, MouseUpCommandCanExecute); // } // return mouseDownCommand; // } //} private bool MouseDownCommandCanExecute(object? obj) { return true; } private int itemsCount = 0; private int idx = 0; private void MouseDownCommandExecuted(object? obj) { if (obj != null && obj is MouseEventArgs e) { var pos = e.GetPosition(null); string str = $"{++idx},X:{pos.X},Y:{pos.Y}"; PosStrList.Add(str); itemsCount = PosStrList.Count; SelectedItem = PosStrList[itemsCount - 1]; } } } public static class MouseBehavior { public static readonly DependencyProperty MouseDownCommandProperty = DependencyProperty.RegisterAttached("MouseDownCommand", typeof(ICommand), typeof(MouseBehavior), new PropertyMetadata(null, OnMouseDownCommandChanged)); public static void SetMouseDownCommand(DependencyObject dObj, ICommand commandValue) { dObj.SetValue(MouseDownCommandProperty, commandValue); } public static ICommand GetMouseDownCommand(DependencyObject dObj) { return (ICommand)dObj.GetValue(MouseDownCommandProperty); } private static void OnMouseDownCommandChanged(DependencyObject dObj, DependencyPropertyChangedEventArgs e) { if (dObj is UIElement element) { if (e.NewValue != null) { element.MouseDown += Element_MouseDown; } else { element.MouseDown -= Element_MouseDown; } } } private static void Element_MouseDown(object sender, MouseButtonEventArgs e) { var element = sender as UIElement; if (element != null) { var command = GetMouseDownCommand(element); if (command?.CanExecute(e) == true) { command.Execute(e); } } } } public class DelCommand : ICommand { private Action<object?> execute; private Predicate<object?> canExecute; public DelCommand(Action<object?> executeValue, Predicate<object?> canExecuteValue) { execute = executeValue; canExecute = canExecuteValue; } public event EventHandler? CanExecuteChanged { add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; } } public bool CanExecute(object? parameter) { if (canExecute == null) { return true; } return canExecute(parameter); } public void Execute(object? parameter) { execute(parameter); } } }