WPF(Livet)でBehaviorを利用してViewからViewModelにデータを渡す

LivetでViewからViewModelにデータを渡すとき、
例えばViewModelCommandを利用して、「ボタンを押したときにTextの値を読み込む」等が例として挙げられていますが、
そのようなやり方ではなく、ViewからViewModelにトリガ経由で値を渡したくなる時があります。
例えば、
・画像をクリックしたとき
・マウスのホイールを動かしたとき
・マウスのカーソルを動かしたとき
等々。。。

そんな時はBehaviorを利用して、値を渡します。
次の例は「表示した画像の中でマウスカーソルが示すPixel数をTextに表示させる」というものです。




 ファイルの構成は以下のようになります。Behaviorフォルダを切って、MouseMoveBehavior.csを新規追加します。


まずは、XAMLです。今回はGrid外にも編集しているので、全部載せます。
xmlns:b="clr-namespace:LivetSample.Behaviors"
XAMLからMouseMoveBehavior.csにアクセスできるようにしているので、


























次にViewModelです。
ここでは、MouseMoveのトリガを受けるListenerCommandを定義しています。
そこでViewにBindingしているMousePosに値を代入しています。
using Microsoft.Win32;
using System.Windows;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;
using OpenCvSharp;
using OpenCvSharp.Extensions;

namespace LivetSample.ViewModels
{
public class MainWindowViewModel : ViewModel
{
public void Initialize()
{
}

#region FileUri変更通知プロパティ
private string _FileUri;

public string FileUri
{
get
{ return _FileUri; }
set
{
if (_FileUri == value)
return;
_FileUri = value;
RaisePropertyChanged();
}
}
#endregion

#region MousePos変更通知プロパティ
private Point _MousePos;

public Point MousePos
{
get
{ return _MousePos; }
set
{
if (_MousePos == value)
return;
_MousePos = value;
RaisePropertyChanged();
}
}
#endregion

#region WBitmap変更通知プロパティ
private WriteableBitmap _WBitmap;

public WriteableBitmap WBitmap
{
get
{ return _WBitmap; }
set
{
if (_WBitmap == value)
return;
_WBitmap = value;
RaisePropertyChanged();
}
}
#endregion

#region FileOpenCommand
private ViewModelCommand _FileOpenCommand;

public ViewModelCommand FileOpenCommand
{
get
{
if (_FileOpenCommand == null)
{
_FileOpenCommand = new ViewModelCommand(FileOpen);
}
return _FileOpenCommand;
}
}

public void FileOpen()
{
OpenFileDialog dlg = new OpenFileDialog();
dlg.Title = "ファイルを開く";
dlg.Filter = "画像ファイル|*.jpg";
if (dlg.ShowDialog() == true)
{
FileUri = dlg.FileName;
using (var img = new IplImage(FileUri))
{
WBitmap = img.ToWriteableBitmap();
}
}
}
#endregion

#region MouseMoveCommand
private ListenerCommand _MouseMoveCommand;

public ListenerCommand MouseMoveCommand
{
get
{
if (_MouseMoveCommand == null)
{
_MouseMoveCommand = new ListenerCommand(MouseMove);
}
return _MouseMoveCommand;
}
}

public void MouseMove(Point parameter)
{
MousePos = parameter;
}
#endregion
}
}


最後にMouseMoveBehavior.csです。ここでBehaviorを定義しています。
これは使用したいBehaviorごとに自分で作っていかないといけないみたいですね。。。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

using Livet;
using Livet.Commands;
using Livet.Messaging;
using Livet.Messaging.IO;
using Livet.EventListeners;
using Livet.Messaging.Windows;

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

namespace LivetSample.Behaviors
{
public class MouseMoveAction : TriggerAction
{
public static readonly DependencyProperty CommandProperty = DependencyProperty.Register(
"Command", typeof(ICommand), typeof(MouseMoveAction), new UIPropertyMetadata(null)
);

public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}

protected override void Invoke(object parameter)
{
var eventArgs = parameter as MouseEventArgs;
var element = AssociatedObject as IInputElement;

if (Command == null || eventArgs == null || element == null) return;
var position = eventArgs.GetPosition(element);

if (Command.CanExecute(position))
{
Command.Execute(position);
}
}
}
}