ページ

2010年8月3日火曜日

[Silverlight] ビヘイビアーの開発 その3

[Silverlight] ビヘイビアーの開発 その2」 の続きです。

■ サンプル
トリガーをきっかけにストーリーボードを開始するビヘイビアーを作ってみます。
と言っても、たいしたものではなく、基本的には

  • Storyboard 依存プロパティを定義する。
  • Invoke メソッドで Storyboard 依存プロパティのストーリーボードを開始する。

としてやればいいだけです。(実際にはこれだけではちょっと問題があります。それについては後述)
実際のコードは以下のようになります。

public class PlayStoryboardBehavior : TriggerAction<FrameworkElement>
{
    public Storyboard Storyboard
    {
        get { return (Storyboard)GetValue(StoryboardProperty); }
        set { SetValue(StoryboardProperty, value); }
    }

    public static readonly DependencyProperty StoryboardProperty =
        DependencyProperty.Register("Storyboard", typeof(Storyboard), typeof(PlayStoryboardBehavior), null);

    protected override void Invoke(object parameter)
    {
        if (this.Storyboard != null)
        {
            this.Storyboard.Begin();
        }
    }
}

■ CustomPropertyValueEditor 属性
上記のコードで一番の問題はストーリーボードの選択が Blend 上できちんとできないことです。
Storyboard プロパティの部分は以下のようになっています。

PlayStoryboardBehavior_StoryboardProp1.jpg

XAML 上にストーリーボードがあっても 「新規作成」 ボタンしか無いためそれらを選択することができません。これでは実用的に使うことができません。(XAML を手で編集すれば使うことはできると思いますが)
これを可能にするための専用の属性 CustomPropertyValueEditor が用意されています。

    [CustomPropertyValueEditor(CustomPropertyValueEditor.Storyboard)]
    public Storyboard Storyboard
    {
        get { return (Storyboard)GetValue(StoryboardProperty); }
        set { SetValue(StoryboardProperty, value); }
    }

このように Storyboard 依存プロパティに CustomPropertyValueEditor(CustomPropertyValueEditor.Storyboard) を追加してやるだけです。
このようにすると Blend 上での表示が以下のようになります。

PlayStoryboardBehavior_StoryboardProp2.jpg

ちゃんとドロップダウンコンボボックスになって既存のストーリーボードを選択できるようになりました。

なお、CustomPropertyValueEditor は他にもいくつか用意されています。詳しくはリファレンスマニュアルの 「CustomPropertyValueEditor 列挙」 を。

■ Category 属性
プロパティに Category 属性を付けておくと Blend のプロパティウインドウ上での表示場所を指定することができます。

    [Category("Common Properties")]
    [CustomPropertyValueEditor(CustomPropertyValueEditor.Storyboard)]
    public Storyboard Storyboard
    {
        get { return (Storyboard)GetValue(StoryboardProperty); }
        set { SetValue(StoryboardProperty, value); }
    }

このように Category("Common Properties") を付けてやると 「その他」 ではなく下図のように 「共通プロパティ」 の方に入るようになります。

PlayStoryboardBehavior_StoryboardProp3.jpg

■ DefaultTrigger 属性
トリガーのデフォルト値についてですが、Button に接続した場合は Click イベントがデフォルトとなるようです。
しかし、他の多くのオブジェクトでは Loaded がデフォルトとなってしまいます。以下は TextBlock に接続したときのトリガーのデフォルト値です。

PlayStoryboardBehavior_TriggerProp1.jpg

今回のような 「ストーリーボードを開始するビヘイビアー」 の場合は、ボタンでは Click イベント、それ以外では MouseLeftButtonDown イベントあたりをデフォルトにしておきたいところです。
それが、DefaultTrigger 属性で指定できます。

[DefaultTrigger(typeof(Button), typeof(System.Windows.Interactivity.EventTrigger), "Click")]
[DefaultTrigger(typeof(FrameworkElement), typeof(System.Windows.Interactivity.EventTrigger), "MouseLeftButtonDown")]
public class PlayStoryboardBehavior : TriggerAction<FrameworkElement>
{
    ...
}

■ サンプルの完成コード
一応、サンプルコードの完成形を載せておきます。 

[DefaultTrigger(typeof(Button), typeof(System.Windows.Interactivity.EventTrigger), "Click")]
[DefaultTrigger(typeof(FrameworkElement), typeof(System.Windows.Interactivity.EventTrigger), "MouseLeftButtonDown")]
public class PlayStoryboardBehavior : TriggerAction<FrameworkElement>
{
    [Category("Common Properties")]
    [CustomPropertyValueEditor(CustomPropertyValueEditor.Storyboard)]
    public Storyboard Storyboard
    {
        get { return (Storyboard)GetValue(StoryboardProperty); }
        set { SetValue(StoryboardProperty, value); }
    }

    public static readonly DependencyProperty StoryboardProperty =
        DependencyProperty.Register("Storyboard", typeof(Storyboard), typeof(PlayStoryboardBehavior), null);

    protected override void Invoke(object parameter)
    {
        if (this.Storyboard != null)
        {
            this.Storyboard.Begin();
        }
    }
}

[Silverlight] ビヘイビアーの開発 その4」 に続きます。

0 件のコメント:

コメントを投稿

注: コメントを投稿できるのは、このブログのメンバーだけです。