WPF “ビヘイビア” なるもの

初心者によるMVVM入門に記載したように、MVVMにおいてViewで処理を行わないことが重要です。イベントハンドラに対してICommandインターフェースを実装したコマンドを用意してバインドするのが1つの手ですが、表示の仕方にしか関わらない内容に対してはもう1つ方法があります、それがビヘイビアです。

 

1.自作する場合

ビヘイビアは、WPFコアが提供する依存関係プロパティ等とはちょっと違い、ビヘイビアは内部的には添付プロパティを使って実現しているそうですので、自作できるはず。。

SelfMadeBehavior.cs

namespace BehaviorTest
{
    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Media.Animation;

    public class SelfMadeBehavior
    {
        public static bool GetEnableAnimation(DependencyObject obj)
        {
            return (bool)obj.GetValue(EnableAnimationProperty);
        }
        public static void SetEnableAnimation(DependencyObject obj, bool value)
        {
            obj.SetValue(EnableAnimationProperty, value);
        }
        public static readonly DependencyProperty EnableAnimationProperty =
            DependencyProperty.RegisterAttached("EnableAnimation", typeof(bool), typeof(SelfMadeBehavior),
            new PropertyMetadata(false, EnableAnimationChanged));

        private static void EnableAnimationChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            Button button = obj as Button;
            if ((bool)e.NewValue)
            {
                button.MouseEnter += button_MouseEnter;
                button.MouseLeave += button_MouseLeave;
            }
            else
            {
                button.MouseEnter -= button_MouseEnter;
                button.MouseLeave += button_MouseLeave;
            }
        }

        private static void button_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
        {
            DoubleAnimation animation = new DoubleAnimation(100, new Duration(new TimeSpan(0, 0, 1)));
            Button button = sender as Button;
            button.BeginAnimation(Button.HeightProperty, animation);
        }
        private static void button_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
        {
            DoubleAnimation animation = new DoubleAnimation(50, new Duration(new TimeSpan(0, 0, 1)));
            Button button = sender as Button;
            button.BeginAnimation(Button.HeightProperty, animation);
        }
    }
}

これをViewで使うのは下のような感じ。まさしく添付プロパティです。

MainWindow.xaml

<Window x:Class="BehaviorTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:me="clr-namespace:BehaviorTest"
        Title="MainWindow" Height="350" Width="205.597">
    <StackPanel >
        <Button Content="Button1" Margin="0,30,0,0" Height="50" Width="75" me:SelfMadeBehavior.EnableAnimation="true"/>
    </StackPanel>
</Window>

1_run

静止画キャプチャでわかりませんが、マウスが入ってきたときに高さが100にアニメートされ、出ていくと50に戻ります。Viewのイベントハンドラを用いずに表示に関する動作が規定できる、かつ再利用できるというのがメリットです。

 

2. ライブラリを使う場合(お勧め)

自作は仕組みを理解するのが目的で、お仕事では迷わずライブラリを使いましょう。

VS2012pro or VS2013proがインストールされている場合は不要ですが、VisualStudio2010やBlendがインストールされていない場合はまずこちらからBlend SDK for .NET4をダウンロード&インストールします。

blend

インストール後、先ほどのWPFプロジェクトに、Microsoft.Expression.Interactionsと、System.Windows.Interactivityを参照追加します。先ほどのビヘイビアをライブラリをつかって書くとこんな感じです。

 LibraryUsedBehavior.cs

namespace BehaviorTest
{
    using System;
    using System.Windows;
    using System.Windows.Input;
    using System.Windows.Controls;
    using System.Windows.Interactivity;
    using System.Windows.Media.Animation;

    public class LibraryUsedBehavior : Behavior<Button>
    {
        protected override void OnAttached()
        {
            base.OnAttached();
            this.AssociatedObject.MouseEnter += AssociatedObject_MouseEnter;
            this.AssociatedObject.MouseLeave += AssociatedObject_MouseLeave;
        }

        protected override void OnDetaching()
        {
            this.AssociatedObject.MouseEnter += AssociatedObject_MouseEnter;
            this.AssociatedObject.MouseLeave += AssociatedObject_MouseLeave;
            base.OnDetaching();
        }

        void AssociatedObject_MouseEnter(object sender, MouseEventArgs e)
        {
            DoubleAnimation animation = new DoubleAnimation(100, new Duration(new TimeSpan(0, 0, 1)));
            Button button = sender as Button;
            button.BeginAnimation(Button.HeightProperty, animation);
        }

        void AssociatedObject_MouseLeave(object sender, MouseEventArgs e)
        {
            DoubleAnimation animation = new DoubleAnimation(50, new Duration(new TimeSpan(0, 0, 1)));
            Button button = sender as Button;
            button.BeginAnimation(Button.HeightProperty, animation);
        }
    }
}

Behavior<T>から派生することでビヘイビアを作成します、ここでTは添付対象のクラスです。OnAttachedとOnDetachingは添付イベントが対象コントロールに添付されたとき、はがされたときに行いたい処理です。これの使い方は以下。

MainWindow.xaml

<Window x:Class="BehaviorTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        xmlns:me="clr-namespace:BehaviorTest"
        Title="MainWindow" Height="350" Width="205.597">
    <StackPanel >
        <Button Content="Button2" Margin="0,30,0,0" Height="50" Width="75" >
            <i:Interaction.Behaviors>
                <me:LibraryUsedBehavior/>
            </i:Interaction.Behaviors>
        </Button>
    </StackPanel>
</Window>

2

動作は先ほど自作した場合と同じ。マウスに応じて高さが変わります。ポイントはやはりコードビハインドのイベントハンドラをがりがり書いていないこと、再利用性が高まります。ただし今回ここで示した例はごく簡単なビヘイビアです、なので以下のようなアニメーションでも全く同じ動きをさせることができます;(わかってますよ、私だって)

MainWindow.xaml

<Window x:Class="BehaviorTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        xmlns:me="clr-namespace:BehaviorTest"
        Title="MainWindow" Height="350" Width="205.597">
    <StackPanel >
        <Button Content="Button3" Margin="0,30,0,0" Height="50" Width="75" >
            <Button.Triggers>
                <EventTrigger RoutedEvent="MouseEnter">
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation To="100" Duration="0:0:1" Storyboard.TargetProperty="Height"/>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
                <EventTrigger RoutedEvent="MouseLeave">
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation To="50" Duration="0:0:1" Storyboard.TargetProperty="Height"/>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Button.Triggers>
        </Button>
    </StackPanel>
</Window>

3

 

3.組み込みのビヘイビア

有名なビヘイビアといえばやっぱりFluidMoveBehavior、レイアウト前後でアイテムの位置が変わる時にその様子をアニメーションするものです。これはXAMLのアニメーションだけでは代替が困難でしょう。しかもこれが簡単に使えるので、機会があれば組込みたくなりますね。

 MainWindow.xaml

<Window x:Class="BehaviorTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
        xmlns:me="clr-namespace:BehaviorTest"
        Title="MainWindow" Height="350" Width="205.597">
    <WrapPanel>
        <i:Interaction.Behaviors>
            <ei:FluidMoveBehavior AppliesTo="Children"/>
        </i:Interaction.Behaviors>
        <Button Content="Button1" Width="75"/>
        <Button Content="Button2" Width="75"/>
        <Button Content="Button3" Width="75"/>
        <Button Content="Button4" Width="75"/>
        <Button Content="Button5" Width="75"/>
        <Button Content="Button6" Width="75"/>
        <Button Content="Button7" Width="75"/>
        <Button Content="Button8" Width="75"/>
        <Button Content="Button9" Width="75"/>
        <Button Content="Button10" Width="75"/>
        <Button Content="Button11" Width="75"/>
        <Button Content="Button12" Width="75"/>
        <Button Content="Button13" Width="75"/>
    </WrapPanel>
</Window>

このXAMLだけでこんな動き↓

before移動のようすafter

うつくしい。

WPF “ビヘイビア” なるもの」への1件のフィードバック

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中