こんにちは、働くC#プログラマーのさんさめです。
GUIのアプリであっても、
頻繁に行われる操作に関しては
キーボードのみで操作できるようにしておくと、
使い勝手がグンと良くなることがあります
今回やりたかったことは、
複数のDataGridが配置されているアプリで、
それぞれのセルを交互に編集したい、
といったケースです。
1つの表を編集しているだけなら、
入力→矢印キーで移動→次の入力…
と、テンポよく編集できます。
しかし、2つの表を行ったり来たりしたい場合は、
矢印キーやTabキーでは、
期待する動作になりません。
特に今回実現したかったことは、
直前まで選択していたセルに
フォーカスを戻す、ということでした。
というわけで、
SelectedCellsの最初をCurrentCellにする、
という方法でこれを実現したので、
備忘録も兼ねて解説して行きたいと思います。
DataGridのFocusを呼ぶだけではダメ
最初に試したのは、
シンプルに対象となるDataGridに対して、
Focusメソッドを呼ぶことでした。
targetGrid.Focus();
しかし、これはうまくいきませんでした。
DataGridそのものにフォーカスが移ってしまい、
そのまま矢印キーを押しても、
最初のセルから移動が始まってしまいます。
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の違い。使い分けが重要
をご覧ください。
コメント