【WPF学習中】MVVMでイベントの発生元のコントロールを引数にする。【MouseMove】

コンピュータ
MVVMでマウスの移動イベントからカーソル位置を拾って表示するサンプルプログラムです。

プロジェクトの作成

PowerShellで実行。要dotnet.exe

mkdir プロジェクト名
cd プロジェクト名
dotnet new wpf
dotnet add package Microsoft.Xaml.Behaviors.Wpf
dotnet add package ReactiveProperty.WPF
code .

ソースコード

ファイル名:MainWindow.xaml

<Window x:Class="MouseMoveSample.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:MouseMoveSample"
        mc:Ignorable="d"
        xmlns:i="clr-namespace:Microsoft.Xaml.Behaviors;assembly=Microsoft.Xaml.Behaviors"
        xmlns:interactivity="clr-namespace:Reactive.Bindings.Interactivity;assembly=ReactiveProperty.WPF"
        Title="MainWindow" Height="450" Width="800">
    <Window.DataContext>
        <local:MainWindowViewModel />
    </Window.DataContext>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <StackPanel Grid.Column="0">
            <Label>X:</Label>
            <TextBox Text="{Binding MouseX.Value}"/>
            <Label>Y:</Label>
            <TextBox Text="{Binding MouseY.Value}"/>
        </StackPanel>
        <Canvas
            x:Name="Canvas1"
            Width = "400"
            Height = "400"
            Background = "LightBlue"
            Grid.Column="1">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="MouseMove">
                    <i:InvokeCommandAction Command="{Binding MouseMoveCommand}" CommandParameter="{Binding ElementName=Canvas1}"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>            
        </Canvas>
    </Grid>
</Window>

ファイル名:MainWindowViewModel.cs

using System.Diagnostics;
using System;
using System.ComponentModel;
using Reactive.Bindings;
using Reactive.Bindings.Extensions;
using System.Reactive.Disposables;

using System.Reactive.Linq;
using System.Collections.Generic;

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

namespace MouseMoveSample
{
    public class MainWindowViewModel : INotifyPropertyChanged, IDisposable
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string name) =>
            PropertyChanged(this, new PropertyChangedEventArgs(name));
        private CompositeDisposable Disposable { get; } = new ();
        public ReactiveCommand<EventArgs> WindowClosedCommand { get; }

        public ReactiveProperty<int> MouseX {get; private set; } = new (0);
        public ReactiveProperty<int> MouseY {get; private set; } = new (0);

        public ReactiveCommand<Object> MouseMoveCommand { get; }

        public MainWindowViewModel()
        {

            PropertyChanged += (o, e) => {};
                        
            WindowClosedCommand = new ReactiveCommand<EventArgs>()
                .WithSubscribe(e =>this.Dispose()).AddTo(Disposable);
            MouseMoveCommand = new ReactiveCommand<object>()
                .WithSubscribe(obj =>
                {
                    // マウス座標の取得
                    var ele = (IInputElement)obj;
                    var pos = Mouse.GetPosition(ele);

                    MouseX.Value = (int)pos.X;
                    MouseY.Value = (int)pos.Y;

                }).AddTo(Disposable);
        }

        public void Dispose()
        {
            Debug.WriteLine("Dispose()");
            Disposable.Dispose();
        }
    }//class
}//ns

実行

dotnet run

説明

サンプル画像にはカーソルが表示されていませんが、右側のCanvas(LightBlue)領域上のマウスの動きに合わせて、左側のX,Yの座標(TextBox)の値が変化します。

コメント