diff --git a/src/TableView.Properties.cs b/src/TableView.Properties.cs
index e592e84..d720982 100644
--- a/src/TableView.Properties.cs
+++ b/src/TableView.Properties.cs
@@ -256,6 +256,9 @@ public partial class TableView
public static readonly DependencyProperty CanReorderColumnsProperty = DependencyProperty.Register(nameof(CanReorderColumns), typeof(bool), typeof(TableView), new PropertyMetadata(true));
///
+ /// Identifies the UseListViewHotkeys dependency property.
+ ///
+ public static readonly DependencyProperty UseListViewHotkeysProperty = DependencyProperty.Register(nameof(UseListViewHotkeys), typeof(bool), typeof(TableView), new PropertyMetadata(false));
/// Identifies the dependency property.
///
public static readonly DependencyProperty ConditionalCellStylesProperty = DependencyProperty.Register(nameof(ConditionalCellStyles), typeof(IList), typeof(TableView), new PropertyMetadata(default));
@@ -768,6 +771,15 @@ public bool CanReorderColumns
set => SetValue(CanReorderColumnsProperty, value);
}
+ ///
+ /// Gets or sets whether the TableView should use ListView like hotkeys for navigation and selection.
+ ///
+ public bool UseListViewHotkeys
+ {
+ get => (bool)GetValue(UseListViewHotkeysProperty);
+ set => SetValue(UseListViewHotkeysProperty, value);
+ }
+
///
/// Handles changes to the ItemsSource property.
///
diff --git a/src/TableView.cs b/src/TableView.cs
index 8de95d1..fee9826 100644
--- a/src/TableView.cs
+++ b/src/TableView.cs
@@ -3,6 +3,7 @@
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Input;
+using Microsoft.UI.Xaml.Media;
using System;
using System.Collections;
using System.Collections.Generic;
@@ -129,6 +130,13 @@ protected override DependencyObject GetContainerForItemOverride()
_rows.Add(row);
return row;
}
+
+ private bool IsRowKeyboardContext =>
+ (UseListViewHotkeys == true) && //Not sure if I'm solving a bug or adding a feature, so I've made it apply only when the UseListViewHotkeys is set to true just in case.
+ (SelectionUnit == TableViewSelectionUnit.Row ||
+ (SelectionUnit == TableViewSelectionUnit.CellOrRow &&
+ LastSelectionUnit == TableViewSelectionUnit.Row));
+
///
protected override async void OnKeyDown(KeyRoutedEventArgs e)
@@ -142,9 +150,94 @@ protected override async void OnKeyDown(KeyRoutedEventArgs e)
return;
}
+ if (!IsEditing && IsRowKeyboardContext)
+ {
+ if (!shiftKey &&
+ !ctrlKey &&
+ SelectionMode == ListViewSelectionMode.Multiple &&
+ e.Key == VirtualKey.Enter)
+ {
+ ToggleCurrentRowSelection();
+ e.Handled = true;
+ return;
+ }
+
+ var rowSelectionOnly = SelectionUnit == TableViewSelectionUnit.Row;
+
+ if (e.Key is VirtualKey.Up or VirtualKey.Down or
+ VirtualKey.Home or VirtualKey.End or
+ VirtualKey.PageUp or VirtualKey.PageDown ||
+ (rowSelectionOnly && (e.Key is VirtualKey.Left or VirtualKey.Right)))
+ {
+ int? prevCellRow = null;
+ if (SelectionUnit == TableViewSelectionUnit.Row && CurrentCellSlot.HasValue)
+ {
+ prevCellRow = CurrentCellSlot.Value.Row;
+ }
+
+ base.OnKeyDown(e); // Let ListView move the row focus / selection
+
+ var focusedIndex = GetFocusedRowIndex();
+ if (focusedIndex >= 0)
+ {
+ CurrentRowIndex = focusedIndex;
+ SelectionStartRowIndex ??= focusedIndex;
+ }
+
+ if (SelectionUnit == TableViewSelectionUnit.Row &&
+ prevCellRow.HasValue &&
+ focusedIndex >= 0 &&
+ focusedIndex != prevCellRow.Value)
+ {
+ CurrentCellSlot = null; // will un-apply old cell's current-state border
+ }
+ return;
+ }
+ }
+ // Everything else (cell nav, F2 in cell mode, Space, etc.)
await HandleNavigations(e, shiftKey, ctrlKey);
}
+
+
+ private void ToggleCurrentRowSelection()
+ {
+
+ var index = GetFocusedRowIndex();
+
+ if (index < 0)
+ {
+ var rowIndex = CurrentRowIndex ?? SelectedIndex;
+
+ if (rowIndex is < 0 || rowIndex >= Items.Count)
+ {
+ return;
+ }
+
+ index = rowIndex;
+ }
+
+
+ if (index < 0 || index >= Items.Count) { return; }
+
+ var isSelected = SelectedRanges.Any(r => r.IsInRange(index));
+
+ var singleIndexRange = new ItemIndexRange(index, 1u);
+
+ if (isSelected)
+ {
+ DeselectRange(singleIndexRange);
+ }
+ else
+ {
+ SelectRange(singleIndexRange);
+ }
+
+ SelectionStartRowIndex = index;
+ CurrentRowIndex = index;
+
+ }
+
///
/// Handles navigation keys.
///
@@ -385,6 +478,34 @@ private TableViewCellSlot GetNextSlot(TableViewCellSlot? currentSlot, bool isShi
return new TableViewCellSlot(nextRow, nextColumn);
}
+ private int GetFocusedRowIndex()
+ {
+ if (XamlRoot is null)
+ return -1;
+
+ var focused = FocusManager.GetFocusedElement(XamlRoot) as DependencyObject;
+ if (focused is null)
+ return -1;
+
+ var row = GetRowFromElement(focused);
+ return row?.Index ?? -1;
+ }
+
+ private static TableViewRow? GetRowFromElement(DependencyObject element)
+ {
+ var current = element;
+
+ while (current is not null)
+ {
+ if (current is TableViewRow row)
+ return row;
+
+ current = VisualTreeHelper.GetParent(current);
+ }
+
+ return null;
+ }
+
///
/// Copies the selected rows or cells content to the clipboard.
///