【WPF】DataGridにフォーカスしたい時はセルにフォーカスしよう

C#

こんにちは、働くC#プログラマーのさんさめです。

GUIのアプリであっても、
頻繁に行われる操作に関しては
キーボードのみで操作できるようにしておくと、
使い勝手がグンと良くなることがあります

今回やりたかったことは、
複数のDataGridが配置されているアプリで、
それぞれのセルを交互に編集したい、
といったケースです。

1つの表を編集しているだけなら、
入力→矢印キーで移動→次の入力…
と、テンポよく編集できます。

しかし、2つの表を行ったり来たりしたい場合は、
矢印キーやTabキーでは、
期待する動作になりません。

特に今回実現したかったことは、
直前まで選択していたセルに
フォーカスを戻す、ということでした。

というわけで、
SelectedCellsの最初をCurrentCellにする、
という方法でこれを実現したので、
備忘録も兼ねて解説して行きたいと思います。

スポンサーリンク

DataGridのFocusを呼ぶだけではダメ

最初に試したのは、
シンプルに対象となるDataGridに対して、
Focusメソッドを呼ぶことでした。

targetGrid.Focus();

しかし、これはうまくいきませんでした
DataGridそのものにフォーカスが移ってしまい、
そのまま矢印キーを押しても、
最初のセルから移動が始まってしまいます。

Ctrl+Tでフォーカスが移動してます

DataGridで特定のセルにフォーカスするにはCurrentCell

調べたところ、
特定のセルにフォーカスするためには、
CurrentCellに代入する必要があるとのことでした。

そこで、
次のように書き換えました。

var cellInfo = targetGrid.SelectedCells.FirstOrDefault();
targetGrid.Focus();
targetGrid.CurrentCell = cellInfo;

フォーカスが外れても
選択セル(SelectedCells)は、
記憶されていることを利用して、
選択セルの一番最初のセルにフォーカスするという作戦です。

これを実行した結果は、
次のようになりました。

良い感じの動作になりました。
複数セル選択していた場合は、
期待した動作にならないかもしれませんが、
編集するというユースケースから考えると
そこまでのケアは必要なさそうでした。

さんさめ
さんさめ

うん、いい感じ!
これでリリースしよ~

ところが、
リリースしてほどなく、
使いづらいとの声が上がりました。

初回だけうまく動作しないんですよ~

まだSelectedCellsが無いときのケアが必要だった

よくよく調べてみると、
初回とは、すなわち
「まだSelectedCellsが無いとき」
にこの処理が実行されると、
うまく動作しないということでした。

実際にその動作を行った結果がこちらです。
(実は先ほどの動画はすでにどちらのセルも
一度以上選択した後に録っていました)

どうあっても、
右のDataGrid内のセルに
フォーカスが移りませんね。

さんさめ
さんさめ

はァーーッ!なるほどね!!
直します!

といっても、選択セルが1つもない場合は、
どうしようもないので、
とりあえず存在するセルの最初を選ぶようにしましょう。

その修正コードが以下です。

var cellInfo = targetGrid.SelectedCells.FirstOrDefault();
targetGrid.Focus();
if (cellInfo.Equals(default(DataGridCellInfo)))
{
    cellInfo = new DataGridCellInfo(targetGrid.ItemsSource.OfType<object>().FirstOrDefault(),
        targetGrid.Columns.FirstOrDefault());
    targetGrid.SelectedCells.Add(cellInfo);
}
targetGrid.CurrentCell = cellInfo;

もし、選択セルが1つもない場合は、
最初のFirstOrDefaultの結果が、
DataGridCellInfo構造体の既定値となります。

その場合は、最初の行、最初の列の情報から、
新しいDataGridCellInfoを作り、
CurrentCellに代入しています。

また、CurrentCellに代入を行うだけでは、
選択状態にはなっておらず、
見た目がおかしくなるため、
SelectedCellsへの追加も行っています。

これを実行した結果が以下です。

選択セルが無い状態でフォーカスを移動させた場合は、
左上のセルがフォーカスされるようになりました。

これで、キーボード操作だけで2つの
DataGridの編集ができるようになりました。

まとめ

まとめです。

  • DataGridのセルにフォーカス移動させるにはCurrentCell
  • 直前に選択していたセルはSelectedCellsから取得できる
  • SelectedCellsが無いときは存在する最初のセルに
    フォーカスしてあげると親切

最後までお読みいただき、ありがとうございました。

関連記事

今回のように、
Viewだけで完結する処理の場合は、
ViewModelにコードを書くのは逆に不適切です。

RoutedCommandを使ってView側に
全ての実装を行うべきでしょう。

今回の話は、
「そもそもSelectedCellsが使える」
ことが前提です。
DataGridにおけるSelectedItemsとSelectedCellsの
違いが良く分からない人は、
【WPF】SelectedItemsとSelectedCellsの違い。使い分けが重要
をご覧ください。

コメント

タイトルとURLをコピーしました