Tôi đã thử các đề xuất này và nhiều đề xuất khác mà tôi đã tìm thấy trên các trang web khác, nhưng không có đề xuất nào phù hợp với tôi. Cuối cùng, tôi đã tạo ra giải pháp sau đây.
Tôi đã tạo điều khiển được kế thừa DataGrid của riêng mình và chỉ cần thêm mã này vào nó:
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;
}
}
Tất cả những điều này làm gì?
Chà, mỗi lần chúng tôi nhấp vào bất kỳ ô nào trong DataGrid, chúng tôi sẽ xem liệu ô đó có chứa điều khiển CheckBox bên trong nó không. Nếu đúng như vậy , thì chúng ta sẽ đặt trọng tâm vào CheckBox đó và chuyển đổi giá trị của nó .
Điều này dường như làm việc cho tôi, và là một giải pháp tốt đẹp, dễ dàng tái sử dụng.
Thật đáng thất vọng khi chúng ta cần phải viết mã để làm điều này mặc dù. Giải thích rằng lần nhấp chuột đầu tiên (trên CheckBox của DataGrid) bị "bỏ qua" vì WPF sử dụng nó để đưa hàng vào chế độ Chỉnh sửa nghe có vẻ hợp lý, nhưng trong thế giới thực, điều này đi ngược lại cách mọi ứng dụng thực hoạt động.
Nếu người dùng nhìn thấy một hộp kiểm trên màn hình của họ, họ sẽ có thể nhấp vào nó một lần để đánh dấu / bỏ chọn nó. Kết thúc câu chuyện.