【WPF】DataGrid 行をクリックしたときに ViewModel のコマンドを確実に発火させる方法
── Behavior + InvokeCommandAction で MVVM を崩さず実現する
WPF の DataGrid を使っていると、次のような要望がよくあります。
- 行をクリックするだけで ViewModel のメソッドを実行したい
- 同じ行を連続クリックしても毎回発火してほしい
- コードビハインドには書きたくない(MVVMを崩したくない)
しかし、SelectionChanged では 同じ行を連続クリックしても発火しない ので条件を満たせません。
そこで本記事では、
- 左クリックのたびに ViewModel のコマンドを確実に実行する方法
を Behavior / EventTrigger / InvokeCommandAction で実装していきます。
🎯 完成イメージ
- DataGrid の行を左クリックすると ViewModel の
RowClickCommandが呼ばれる - その行のデータ(EmployeeDModel など)がコマンドパラメータとして渡る
- コードビハインドは書かない
🔧 必要ライブラリ
- NuGet から追加:
Microsoft.Xaml.Behaviors.Wpf
🧩 XAML の先頭に必要な名前空間
まずこの 1 行目〜6 行目がないと Behaviors が使えません。役割も記載します。
<Window x:Class="MvvmSample.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MvvmSample"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
Title="MainWindow" Height="450" Width="800">
| 宣言 | 役割 |
|---|---|
| xmlns | WPF 標準コントロール(Button, Grid 等)を使う |
| xmlns:x | x:Class / x:Name など XAML 文法用 |
| xmlns:local | 自作クラス(UserControl等)を XAMLで使うとき |
| xmlns:i | Interaction.Triggers / InvokeCommandAction を使うため |
今回の記事で重要なのは 4 行目の xmlns:i。これを入れないと InvokeCommandAction が使えません。
🧱 DataGrid に左クリックコマンドを追加する XAML
<DataGrid x:Name="EmployeeGrid"
ItemsSource="{Binding Items}"
SelectedItem="{Binding SelectedEmployee}"
AutoGenerateColumns="True"
IsReadOnly="True">
<i:Interaction.Triggers>
<!-- 左クリックでコマンドを実行 -->
<i:EventTrigger EventName="MouseLeftButtonUp">
<i:InvokeCommandAction
Command="{Binding RowClickCommand}"
CommandParameter="{Binding SelectedItem, ElementName=EmployeeGrid}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</DataGrid>
🔍 動作の流れ
| クリック操作 | 何が起きるか |
|---|---|
| 行を左クリック | MouseLeftButtonUp が発生 |
| EventTrigger が拾う | InvokeCommandAction を起動 |
| InvokeCommandAction が ViewModel の RowClickCommand を実行 | その時の SelectedItem がコマンドの引数になる |
ポイント
| 要素 | 重要な点 |
|---|---|
| EventName="MouseLeftButtonUp" | 「クリック後に実行」なので誤作動が少ない。必要なら PreviewMouseLeftButtonDown に変更してセルがハンドルする前に拾ってもよい。 |
| Command="{Binding RowClickCommand}" | DataGrid の DataContext(ViewModel)のコマンド。 |
| CommandParameter="{Binding SelectedItem, ElementName=EmployeeGrid}" | クリック時の行データをそのまま渡す。 |
🧠 ViewModel 側(CommunityToolkit.Mvvm 使用)
[RelayCommand]
private void RowClick(EmployeeDModel? row)
{
if (row == null)
{
return;
}
MessageBox.Show($"{row.Name} がクリックされました。");
}
-
[RelayCommand]によってRowClickCommandが自動生成。 - パラメータ
rowには DataGrid のSelectedItemが渡ってくる。
⚡ この方法のメリット
| 項目 | 理由 |
|---|---|
| 同じ行の連続クリックでも毎回発火 | EventTrigger を直接クリックにバインドしているため |
| コードビハインド不要 | MVVM を壊さない |
| DataGrid のどのセルをクリックしても動作 | セルイベントを意識しなくてよい |
| 可読性・拡張性が高い | Trigger / Action が UI 側の振る舞いとして完結している |
❌ よくある失敗原因
| 現象 | 原因 |
|---|---|
| メソッドが呼ばれない |
Microsoft.Xaml.Behaviors.Wpf が未インストール |
| Binding エラーで null が届く |
x:Name="EmployeeGrid" が付いていない |
| コンパイルエラー |
xmlns:i="http://schemas.microsoft.com/xaml/behaviors" を宣言していない |
🎉 まとめ
DataGrid のクリック処理には SelectionChanged よりも EventTrigger + InvokeCommandAction が適しています。
- 左クリックのたびに確実にコマンド実行
- 連続クリックでも毎回発火
- MVVM を崩さない
- 実装がシンプル
✨ 次に拡張したくなったら…
今の構成に追加するだけで実現できます。
| やりたいこと | 追加するもの |
|---|---|
| ダブルクリックで編集画面を出したい | EventName="MouseDoubleClick" |
| 右クリック選択をしたい | ビヘイビア(PreviewMouseRightButtonDown) |
| Ctrl + クリックで複数選択 | ビヘイビア |
以上、「WPF DataGrid 行の左クリック挙動を MVVM で確実に処理する方法」でした。質問・改善案・応用パターンの相談があれば気軽にコメントください!この記事が開発のお役に立てば嬉しいです 🙌