J'ai essayé ces suggestions et beaucoup d'autres que j'ai trouvées sur d'autres sites, mais aucune d'elles n'a vraiment fonctionné pour moi. En fin de compte, j'ai créé la solution suivante.
J'ai créé mon propre contrôle hérité de DataGrid et j'ai simplement ajouté ce code:
public class DataGridWithNavigation : Microsoft.Windows.Controls.DataGrid
{
public DataGridWithNavigation()
{
EventManager.RegisterClassHandler(typeof(DataGridCell),
DataGridCell.PreviewMouseLeftButtonDownEvent,
new RoutedEventHandler(this.OnPreviewMouseLeftButtonDown));
}
private void OnPreviewMouseLeftButtonDown(object sender, RoutedEventArgs e)
{
DataGridCell cell = sender as DataGridCell;
if (cell != null && !cell.IsEditing && !cell.IsReadOnly)
{
DependencyObject obj = FindFirstControlInChildren(cell, "CheckBox");
if (obj != null)
{
System.Windows.Controls.CheckBox cb = (System.Windows.Controls.CheckBox)obj;
cb.Focus();
cb.IsChecked = !cb.IsChecked;
}
}
}
public DependencyObject FindFirstControlInChildren(DependencyObject obj, string controlType)
{
if (obj == null)
return null;
// Get a list of all occurrences of a particular type of control (eg "CheckBox")
IEnumerable<DependencyObject> ctrls = FindInVisualTreeDown(obj, controlType);
if (ctrls.Count() == 0)
return null;
return ctrls.First();
}
public IEnumerable<DependencyObject> FindInVisualTreeDown(DependencyObject obj, string type)
{
if (obj != null)
{
if (obj.GetType().ToString().EndsWith(type))
{
yield return obj;
}
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
foreach (var child in FindInVisualTreeDown(VisualTreeHelper.GetChild(obj, i), type))
{
if (child != null)
{
yield return child;
}
}
}
}
yield break;
}
}
Que fait tout cela?
Eh bien, chaque fois que nous cliquons sur une cellule de notre DataGrid, nous voyons si la cellule contient un contrôle CheckBox. Si c'est le cas , nous définirons le focus sur cette CheckBox et changerons sa valeur .
Cela semble fonctionner pour moi et c'est une solution agréable et facilement réutilisable.
Il est décevant que nous ayons besoin d'écrire du code pour ce faire. L'explication selon laquelle le premier clic de souris (sur CheckBox d'un DataGrid) est "ignoré" car WPF l'utilise pour mettre la ligne en mode Edition peut sembler logique, mais dans le monde réel, cela va à l'encontre du fonctionnement de chaque application réelle.
Si un utilisateur voit une case à cocher sur son écran, il devrait pouvoir cliquer une fois dessus pour la cocher / décocher. Fin de l'histoire.