読者です 読者をやめる 読者になる 読者になる

かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

WPF4.5入門 その59「Behaviorの自作」

WPF4.5 C# XAML

BehaviorやTriggerとActionを使用することで、簡単なロジックがRAD環境で構築できることがわかりました。ここでは、ありもののBehaviorを使うのではなく自作のBehaviorやTrigger/Actionを作成する方法について示します。Behaviorは、コードビハインドに何回も同じ処理を書いていた場合、作成するとよいことが多いです。では作成したみたいと思います。

Behaviorの自作

ここで作成するのは、ボタンをクリックするとHello worldと表示するBehaviorを自作したいと思います。 Behaviorを作成するために以下のアセンブリを参照に追加します。(Behaviorを使うときにはBlendが自動で追加していたものになります)

  • System.Windows.Interactivity
  • Microsoft.Expression.Interactions

バージョンは4.5のものを追加してください。

Behaviorの作成には、Behaviorクラスを継承します。Behaviorクラスの型引数には、Behaviorを置くことができる型を指定します。特に指定がなければDependencyObjectなどを指定すればよいです。今回はButtonに置くので、Buttonを指定します。またTypeConstraint属性でもBehaviorを置ける型を指定します。

using System;
using System.Windows.Controls;
using System.Windows.Interactivity;

namespace BehaviorSample03
{
    [TypeConstraint(typeof(Button))]
    public class AlertBehavior : Behavior<Button>
    {
    }
}

Behaviorは、対象に設定されたときに呼び出されるOnAttachedメソッドと、対象から外されるときに呼び出されるOnDetachingメソッドをオーバーライドして処理を作成していきます。今回は、OnAttachedメソッドでクリックイベントを購読して、OnDetachingメソッドでクリックイベントの購読を解除します。クリックイベントのイベントハンドラでは、MessageBoxを表示しています。

[TypeConstraint(typeof(Button))]
public class AlertBehavior : Behavior<Button>
{
    protected override void OnAttached()
    {
        // AssociatedObjectのイベントを購読する
        this.AssociatedObject.Click += this.ButtonClicked;
    }

    protected override void OnDetaching()
    {
        // イベントの購読解除
        this.AssociatedObject.Click += this.ButtonClicked;
    }

    // イベントで処理をする
    private void ButtonClicked(object sender, System.Windows.RoutedEventArgs e)
    {
        MessageBox.Show("Hello world");
    }

}

ビルドすると、BlendでAlertBehaviorが使えるようになります。Buttonを画面に置いて、その上にAlertBehaviorをドロップします。

f:id:okazuki:20141222232401p:plain

XAMLを以下に示します。

<Window
    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:local="clr-namespace:BehaviorSample03" 
    x:Class="BehaviorSample03.MainWindow"
    Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Button Content="Button" HorizontalAlignment="Left" 
Margin="10,10,0,0" VerticalAlignment="Top" Width="75">
            <i:Interaction.Behaviors>
                <local:AlertBehavior/>
            </i:Interaction.Behaviors>
        </Button>
    </Grid>
</Window>

実行してボタンをクリックすると、MessageBoxが表示されます。

f:id:okazuki:20141222232453p:plain

TriggerとActionの自作

Triggerを作成するには、System.Windows.Interactivity名前空間のTriggerBaseクラスを継承します。Behaviorと同様にOnAttachedメソッドとOnDetachingメソッドがあるので、そこでイベントを購読するなどのTriggerがActionを実行するためのセットアップをします。TriggerBaseクラスのInvokeActionsメソッドを呼び出すことで、Triggerに設定されたActionを呼び出すことができます。その際に、引数を渡すことでActionに、情報を渡すこともできます。 ここでは、先ほどのAlertBehaviorを、TriggerとActionに分解してみようと思います。Triggerのコードを以下に示します。

using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;

namespace BehaviorSample04
{
    [TypeConstraint(typeof(Button))]
    public class ButtonClickTrigger : TriggerBase<Button>
    {
        protected override void OnAttached()
        {
            this.AssociatedObject.Click += this.ButtonClick;
        }

        private void ButtonClick(object sender, RoutedEventArgs e)
        {
            this.InvokeActions(e);
        }

        protected override void OnDetaching()
        {
            this.AssociatedObject.Click -= this.ButtonClick;
        }
    }
}

Actionは、TriggerActionクラスを継承して、Invokeメソッドをオーバーライドしてそこに処理を記述します。今回のサンプルでは、MessageBoxを表示しています。Behaviorと同様にTypeConstraint属性でActionを置ける型の指定や、DefaultTrigger属性で、デフォルトで設定するTriggerの型を指定できます。(指定しない場合はEventTriggerが使われます)今回の例では、Buttonに置いたときにButtonClickTriggerクラスを使用するように設定しています。コードを以下に示します。

using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;

namespace BehaviorSample04
{
    [TypeConstraint(typeof(Button))]
    [DefaultTrigger(typeof(Button), typeof(ButtonClickTrigger))]
    public class AlertAction : TriggerAction<Button>
    {
        protected override void Invoke(object parameter)
        {
            MessageBox.Show("Hello world");
        }
    }
}

画面にButtonを置いてAlertActionをドロップすると、以下のようなXAMLが生成されます。

<Window
    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:local="clr-namespace:BehaviorSample04" 
    x:Class="BehaviorSample04.MainWindow"
    Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Button Content="Button" HorizontalAlignment="Left" 
                Margin="10,10,0,0" VerticalAlignment="Top" Width="75">
            <i:Interaction.Triggers>
                <local:ButtonClickTrigger>
                    <local:AlertAction/>
                </local:ButtonClickTrigger>
            </i:Interaction.Triggers>
        </Button>
    </Grid>
</Window>

実行すると、Behaviorの時と同様にButtonをクリックするとMessageBoxが表示されます。

過去記事