2016/10/29

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にアクセスできるようにしているので、
<b:MouseMoveAction として、使用できるっていうことですね。






    
        
    

    
        
            
        

        
            
        
    

    
        
        



次に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);
            }
        }
    }
}










0 件のコメント:

コメントを投稿