2013年2月4日月曜日

BehaviorでViewからViewModelのコマンドを実行&パラメータ渡し

ViewからViewModelのコマンドを実行する際に、Behaviorというものを使う方法があるとのことですので動かしてみました(丸パクリですが...)

手順としては
1. 参照設定の追加
Blendの機能なので、Interactivity.dllを参照する
"プロジェクトの参照設定"の"ブラウズ"にて"参照(B)"から
C:\Program Files (x86)\Microsoft SDKs\Expression\Blend\.NETFramework\v4.0\Libraries
の以下の2つのdllを追加
Microsoft.Expression.Interactions.dll
System.Windows.Interactivity.dll
を選択して"追加"する

2. ***Behavior.cs を作成(ここにbeheviorの処理を書いていきたい)

3. usingを追加
using System.Windows.Interactivity;         // 追加
using Microsoft.Expression.Interactivity;   // 追加

4. 監視対象の型のBehaviorを継承したクラスを作成
using が足りないので以下を追加
using System.Windows.Controls;      // コントロール名称を参照する為
using System.Windows;               // DependencyPropertyの定義

監視対象の型のBehaviorを継承したクラスを作成
    public class TestBehavior : Behavior<Button>

5. 依存関係プロパティの定義と登録
作成したクラス内に依存関係プロパティを登録するコードを追加
戻りは"依存関係プロパティ識別子"で"後でプログラムで値を設定したり、メタデータを取得したりする際に、この識別子を使用して依存関係プロパティを参照できます"とのこと
        public static readonly DependencyProperty MessageProperty =
            DependencyProperty.Register("Message" , typeof(string), typeof(TestBehavior),
                            new UIPropertyMetadata(null));

6. (登録される)依存関係プロパティ
        // 公開プロパティ
        private string _message;
        public string Message
        {
            get { return (string)GetValue(MessageProperty); }
            set { SetValue(MessageProperty, value); }
        }

7. 独自ハンドラ(イベント発生時にやりたいこと)追加
        private void Aleart(object sender, EventArgs e)
        {
            if(!string.IsNullOrEmpty(this.Message)){
                MessageBox.Show(this.Message);
            }
        }

8. アタッチ・デタッチ時のハンドラを登録
        /// <summary>
        /// アタッチされた時の処理
        /// </summary>
        protected override void OnAttached()
        {
            base.OnAttached();
            this.AssociatedObject.Click += Alert;
        }

        /// <summary>
        /// デタッチされた時の処理
        /// </summary>
        protected override void OnDetaching()
        {
            base.OnDetaching();
            this.AssociatedObject.Click -= Alert;
        }
9. xamlにBehaviorを呼び出す処理を記載
            <Button Content="Button" HorizontalAlignment="Left" Margin="8,8,0,0" VerticalAlignment="Top" Width="75">
                <i:Interaction.Behaviors>
                    <local:TestBehavior Message="メッセージを渡す"/>
                </i:Interaction.Behaviors>
            </Button>


とりあえずこれで
- ボタンをクリックした時にBehavior側の処理を呼び出す
という事が出来るようです

BreakPointを適当に張ってみると
1. 起動時にアタッチのハンドラが呼ばれる
  ここで"ボタンクリックイベントにメソッドが登録される"模様
2. ボタンを押下すると登録されたメソッドが呼ばれる
  この時、すでに依存関係プロパティにはxaml側の
  "Message="メッセージを渡す"
  という部分が反映されている
という動きの模様

動かしたソースは以下の通り
TestBehavior.cs側
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Windows.Interactivity;         // 追加
using Microsoft.Expression.Interactivity;   // 追加

using System.Windows.Controls;      // コントロール名称を参照する為
using System.Windows;               // DependencyPropertyの定義

using System.Diagnostics;

namespace BehaviorTest
{
    public class TestBehavior : Behavior<Button>
    {
        // 依存関係プロパティの登録
        public static readonly DependencyProperty MessageProperty =
            DependencyProperty.Register("Message", typeof(string), typeof(TestBehavior),
                                        new UIPropertyMetadata(null));

        // 登録される依存関係プロパティ
        public string Message
        {
            get { return (string)GetValue(MessageProperty); }
            set { SetValue(MessageProperty, value); }
        }
       
        /// <summary>
        /// アクションハンドラの記載(ボタン押下時に実行)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Alert(object sender, EventArgs e)
        {
            MessageBox.Show(this.Message);
        }

        /// <summary>
        /// アタッチされた時の処理
        /// </summary>
        protected override void OnAttached()
        {
            base.OnAttached();
            this.AssociatedObject.Click += Alert;
        }

        /// <summary>
        /// デタッチされた時の処理
        /// </summary>
        protected override void OnDetaching()
        {
            base.OnDetaching();
            this.AssociatedObject.Click -= Alert;
        }
    }
}


xaml側のコード
<Window x:Class="BehaviorTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
       
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        xmlns:local="clr-namespace:BehaviorTest"
        >
    <!-- 上記Title以下の2行追加 -->
    <Grid>
        <StackPanel>
            <Button Content="Button" HorizontalAlignment="Left" Margin="8,8,0,0" VerticalAlignment="Top" Width="75">
                <i:Interaction.Behaviors>
                    <local:TestBehavior Message="メッセージを渡す"/>
         <!-- ↑の"Message"がコードにバインドされている模様 -->
                </i:Interaction.Behaviors>
            </Button>
        </StackPanel>
    </Grid>
</Window>


0 件のコメント:

コメントを投稿