diff --git a/samples/TreeDataGridDemo/ViewModels/DynamicColumnsViewModel.cs b/samples/TreeDataGridDemo/ViewModels/DynamicColumnsViewModel.cs index 142d0363..b23a5c7b 100644 --- a/samples/TreeDataGridDemo/ViewModels/DynamicColumnsViewModel.cs +++ b/samples/TreeDataGridDemo/ViewModels/DynamicColumnsViewModel.cs @@ -2,6 +2,7 @@ using Avalonia.Controls; using Avalonia.Controls.Models; using Avalonia.Controls.Models.TreeDataGrid; +using Avalonia.Controls.Selection; using TreeDataGridDemo.Models; namespace TreeDataGridDemo.ViewModels @@ -13,7 +14,7 @@ public DynamicColumnsViewModel() var _data = DataRow.CreateRandomItems(); Source = new HierarchicalTreeDataGridSource(_data); - Source.RowSelection!.SingleSelect = true; + Source.Selection = new TreeDataGridCellSelectionModel(Source); ColumnCount = 20; } diff --git a/src/Avalonia.Controls.TreeDataGrid/Selection/TreeDataGridCellSelectionModel.cs b/src/Avalonia.Controls.TreeDataGrid/Selection/TreeDataGridCellSelectionModel.cs index e70bd892..79df17f6 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Selection/TreeDataGridCellSelectionModel.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Selection/TreeDataGridCellSelectionModel.cs @@ -145,6 +145,9 @@ sender.Rows is null || sender.RowsPresenter?.BringIntoView( rowIndex, sender.ColumnHeadersPresenter?.TryGetElement(columnIndex)?.Bounds); + + if (sender.TryGetCell(columnIndex, rowIndex) is { Focusable: true} targetCell) + targetCell.Focus(); } void ITreeDataGridSelectionInteraction.OnPointerPressed(TreeDataGrid sender, PointerPressedEventArgs e) diff --git a/tests/Avalonia.Controls.TreeDataGrid.Tests/Selection/TreeDataGridCellSelectionTests.cs b/tests/Avalonia.Controls.TreeDataGrid.Tests/Selection/TreeDataGridCellSelectionTests.cs new file mode 100644 index 00000000..66efcfb8 --- /dev/null +++ b/tests/Avalonia.Controls.TreeDataGrid.Tests/Selection/TreeDataGridCellSelectionTests.cs @@ -0,0 +1,108 @@ +using System.Linq; +using Avalonia.Collections; +using Avalonia.Controls.Models.TreeDataGrid; +using Avalonia.Controls.Primitives; +using Avalonia.Controls.Selection; +using Avalonia.Headless; +using Avalonia.Headless.XUnit; +using Avalonia.Input; +using Avalonia.Styling; +using Avalonia.Threading; +using Avalonia.VisualTree; +using Xunit; + +namespace Avalonia.Controls.TreeDataGridTests.Selection; + +public class TreeDataGridCellSelectionTests +{ + [AvaloniaFact] + public void F2_Should_Edit_Current_Cell_After_Arrow_Navigation() + { + var target = CreateTarget(); + var source = (FlatTreeDataGridSource)target.Source!; + var cellSelection = new TreeDataGridCellSelectionModel(source) + { + SingleSelect = true + }; + source.Selection = cellSelection; + + target.GetVisualDescendants() + .OfType() + .First(x => x.RowIndex == 0) + .Focus(); + + cellSelection.SetSelectedRange(new(0, new(0)), 1, 1); + Assert.Single(cellSelection.SelectedIndexes); + Assert.Equal(0, cellSelection.SelectedIndexes[0].RowIndex); + + target.RaiseEvent(new KeyEventArgs + { + RoutedEvent = InputElement.KeyDownEvent, + Key = Key.Down, + }); + + Assert.Single(cellSelection.SelectedIndexes); + Assert.Equal(1, cellSelection.SelectedIndexes[0].RowIndex); + + target.RaiseEvent(new KeyEventArgs + { + RoutedEvent = InputElement.KeyDownEvent, + Key = Key.F2, + }); + + var editingElement = target.GetVisualDescendants() + .OfType() + .FirstOrDefault(x => x.IsFocused && x.IsVisible); + + Assert.NotNull(editingElement); + Assert.Equal(1, editingElement.RowIndex); + } + + private static TreeDataGrid CreateTarget( + int itemCount = 10, + bool runLayout = true) + { + AvaloniaList? items = [.. Enumerable.Range(0, itemCount).Select(x => + new Model + { + Title = "Item " + x, + })]; + + + var source = new FlatTreeDataGridSource(items); + source.Columns.Add(new TextColumn("Title", x => x.Title, (o, v) => o.Title = v)); + + var target = new TreeDataGrid + { + Template = TestTemplates.TreeDataGridTemplate(), + Source = source, + }; + + var root = new TestWindow(target) + { + Styles = + { + new Style(x => x.Is()) + { + Setters = + { + new Setter(TreeDataGridRow.TemplateProperty, TestTemplates.TreeDataGridRowTemplate()), + } + }, + } + }; + + if (runLayout) + { + root.UpdateLayout(); + Dispatcher.UIThread.RunJobs(); + } + + return target; + } + + private class Model + { + public string? Title { get; set; } + } +}