Behaviorを使用してDataGridのダブルクリックイベントを実装する。

以前データグリッドを拡張してダブルクリックイベントを実装しました。

今度はコントロールの継承ではなくBehaviorで実装してみました。

サンプルコードのダウンロード

今回の記事用のサンプルコードを下記からダウンロードすることができます。参考にしてください。

作業の流れ

  1. Expression Blend 4 SDKのインストー
  2. プロジェクトにSystem.Windows.Interactivity.dllを追加する。
  3. DoubleClickBehaviorを実装する。
  4. DataGridを配置しているXAMLにBehavior用xmlnsを追加する。
  5. DataGridにDoubleClickBehaviorを設定する。

Expression Blend 4 SDKのインストー

Behaviorの実装にはExpression Blend 4 SDKが必要となります。Expression Blend 4がインストールされている環境ではSDKのインストールは必要ありません。

プロジェクトにSystem.Windows.Interactivity.dllを追加する。

Blend 4 SDKのSystem.Windows.Interactivity.dllをプロジェクトに追加します。System.Windows.Interactivity.dllないのBehaviorクラスを継承して、ダブルクリックビヘイビアを実装します。

DoubleClickBehaviorを実装する。

DoubleClickBehaviorクラスを作成し、Behaviorクラスを継承します。

// DataGridはこのBehaviorを設定可能なコントロールを指定している。
public class DoubleClickBehavior : Behavior<DataGrid>
{
    protected override void OnAttached()
    {
        base.OnAttached();
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
    }
}

後は、ダブルクリック処理をコーディングします。BehaviorクラスのOnAttachedメソッドが呼ばれるとき、AssociatedObjectプロパティにDataGridインスタンスがセットされことさえ抑えておけば、DataGridを継承して作成したコードをほぼ流用できます。

// DataGridはこのBehaviorを設定可能なコントロールを指定している。
public class DoubleClickBehavior : Behavior<DataGrid>
{
    private const int DoubleClickDureationMilliSeconds = 250;
    private LastClickInfo lastClickInfo = LastClickInfo.Empty;

    /// <summary>
    /// ダブルクリックされたときに発行する。
    /// </summary>
    public event EventHandler DoubleClick;

    protected override void OnAttached()
    {
        base.OnAttached();

        this.AssociatedObject.LoadingRow += this.AssociatedObjectLoadingRow;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();

        this.AssociatedObject.LoadingRow -= this.AssociatedObjectLoadingRow;
        this.AssociatedObject.UnloadingRow -= this.AssociatedObjectUnloadingRow;
    }

    private void AssociatedObjectLoadingRow(object sender, DataGridRowEventArgs e)
    {
        DataGridRow row = e.Row;

        // DataGridRowにダブルクリック検知用イベントハンドラを追加する。
        row.MouseLeftButtonUp -= this.RowMouseLeftButtonUp;
        row.MouseLeftButtonUp += this.RowMouseLeftButtonUp;
    }

    private void AssociatedObjectUnloadingRow(object sender, DataGridRowEventArgs e)
    {
        DataGridRow row = e.Row;
        row.MouseLeftButtonUp -= new MouseButtonEventHandler(this.RowMouseLeftButtonUp);
    }

    private void RowMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        DateTime now = DateTime.Now;
        DateTime lastClickTime = this.lastClickInfo.Time;
        DataGridRow lastClickRow = this.lastClickInfo.Row;

        // 直前にクリックされた行が今回クリックされた行と一致し、
        // かつ、クリックされた間隔が一定時間以内に収まっているか?
        if (lastClickRow == sender
            && (now - lastClickTime).TotalMilliseconds < DoubleClickDureationMilliSeconds)
        {
            // 直前にクリックされた情報を初期化。
            this.lastClickInfo = LastClickInfo.Empty;

            // ダブルクリックイベントを発行
            this.RaiseDoubleClick(sender as DataGridRow);
        }
        else
        {
            // クリックした行情報を保持しておく
            this.lastClickInfo = new LastClickInfo(now, sender as DataGridRow);
        }
    }

    private void RaiseDoubleClick(DataGridRow row)
    {
        if (this.DoubleClick != null)
        {
            this.DoubleClick(row, EventArgs.Empty);
        }
    }

    /// <summary> クリックした行情報を保持する。 </summary>
    private class LastClickInfo
    {
        public static readonly LastClickInfo Empty = new LastClickInfo(DateTime.MinValue, null);

        public LastClickInfo(DateTime time, DataGridRow row)
        {
            this.Time = time;
            this.Row = row;
        }

        /// <summary> クリックされた時間を取得する。 </summary>
        public DateTime Time { get; private set; }

        /// <summary> クリックされた行を取得する。 </summary>
        public DataGridRow Row { get; private set; }
    }
}

DataGridを配置しているXAMLにBehavior用xmlnsを追加する。

Behaviorの定義が終わったので、今度はBehaviorを利用してみます。まず、UserControlのXAMLにBehavior用xmlnsを追加しましょう。

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:behaviors="clr-namespace:Behaviors;assembly=Behaviors"

xmlns:behaviorsbehaviorsのほうは、自分の環境に合わせて修正する必要があります。

DataGridにDoubleClickBehaviorを設定する。

実際にDataGridにDoubleClickBehaviorを設定します。DoubleClickBehaviorのDoubleClickイベントにコマンドをさしてみても良いかもしれません。

<sdk:DataGrid x:Name="DoubleClickDataGrid" IsReadOnly="True">
    <i:Interaction.Behaviors>
        <behaviors:DoubleClickBehavior DoubleClick="DoubleClickBehavior_DoubleClick"/>
    </i:Interaction.Behaviors>
</sdk:DataGrid>

後は、DataGridに適当にデータを流し込んで実行してみれば無事実装できたことを確認できるでしょう。

まとめ

Behaviorを使用してDataGridでダブルクリックイベントを実装しました。