Skip to content

Add Row Editing Highlight and Tap-to-Edit support for Row selection Mode#342

Open
rashmi-thakurr wants to merge 2 commits intow-ahmad:mainfrom
DDancingDeath:feature/cell-editing-row-mode
Open

Add Row Editing Highlight and Tap-to-Edit support for Row selection Mode#342
rashmi-thakurr wants to merge 2 commits intow-ahmad:mainfrom
DDancingDeath:feature/cell-editing-row-mode

Conversation

@rashmi-thakurr
Copy link
Copy Markdown

@rashmi-thakurr rashmi-thakurr commented Apr 9, 2026

Summary

Adds visual row-editing highlight and tap-to-edit support for Row and CellOrRow selection modes, so the active row is clearly indicated while a cell is being edited, matching Windows File Explorer's behavior.

Closes #336

Key Implementation Details

  • Editing highlight overlay: When editing begins, a semi-transparent Border overlay in TableViewRowPresenter becomes visible on the active row. The overlay sits above the RootPanel (hit-test invisible)
    and is completely independent of the row's background — no interaction with EnsureAlternateColors, no platform branching.
  • TapToEdit property: New bool dependency property on TableView, defaults to false. When enabled, a second tap on an already-selected cell starts inline editing (tap-pause-tap like File Explorer rename).
    Double-tap editing is not guarded by this property.
  • Pointer hover for Row/CellOrRow: Added per-cell pointer hover when individual cells are editable, even if the table is globally read-only.
  • Tab wraps row in Row mode: GetNextSlot now treats Tab like Enter when SelectionUnit is Row, so Tab advances to the next row instead of cycling through cells.
  • Theme resources: New TableViewRowEditingHighlightBackground resource in Resources.xaml SubtleFillColorSecondaryBrush for Light/Dark, accent-tinted with 0.3 opacity for HighContrast.
  • Sample app: Added TapToEdit toggle in SelectionPage.xaml to demonstrate the tap-to-edit feature.
Screen.Recording.2026-04-14.112409.mp4

Test Coverage

8 new tests in TableViewRowEditingTests.cs covering: editing highlight in Row mode, editing highlight in CellOrRow mode, pointer hover prerequisites, tap-to-edit prerequisites, virtualization recycling,
current-cell state reset, and editing state transitions across rows.

All 174 tests pass (existing + new).

Files Changed

9 files changed, +404 / −3 lines

File Changes Description
src/TableView.cs +13 / −1 Defensive highlight reset in PrepareContainerForItemOverride, Tab-wraps-row in GetNextSlot
src/TableView.Properties.cs +14 / −0 TapToEdit dependency property and CLR property
src/TableViewCell.cs +30 / −2 Highlight in PrepareForEdit/EndEditing, TapToEdit guard in OnTapped, CellOrRow pointer hover
src/TableViewRow.cs +8 / −0 ApplyEditingHighlight delegates to presenter
src/TableViewRowPresenter.cs +13 / −0 EditingHighlightOverlay template child, ApplyEditingHighlight method
src/Themes/TableViewRowPresenter.xaml +5 / −0 EditingHighlightOverlay Border after RootPanel
src/Themes/Resources.xaml +3 / −0 TableViewRowEditingHighlightBackground for Light, Dark, HighContrast
samples/.../SelectionPage.xaml +4 / −0 TapToEdit toggle in sample app
tests/TableViewRowEditingTests.cs +314 (new) 8 architecture-first UI tests

@rashmi-thakurr rashmi-thakurr force-pushed the feature/cell-editing-row-mode branch from cf3ad20 to 5dbf5b6 Compare April 10, 2026 08:11
@rashmi-thakurr rashmi-thakurr force-pushed the feature/cell-editing-row-mode branch from 5dbf5b6 to 7264709 Compare April 10, 2026 08:14
Comment thread src/TableView.cs
do
{
newSlot = GetNextSlot(newSlot, shiftKey, e.Key is VirtualKey.Enter);
newSlot = GetNextSlot(newSlot, shiftKey, e.Key is VirtualKey.Enter || (e.Key is VirtualKey.Tab && SelectionUnit is TableViewSelectionUnit.Row));
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this isn't right because the tab key should always put the next editable cell in the same row. If there is no editable cell in the same row, it will automatically jump to the next row or previous row with shift + tab.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, GetNextSlot already cycles through editable cells and wraps to the next row on its own.

What we were going for is the File Explorer–style behavior where Tab during rename jumps to the next row and starts editing it. Tab feels natural for quick back-to-back editing since it's the standard "next field" key. We tied it to SelectionUnit.Row because in Row mode the user is already working row by row, so it felt like a natural fit.

If we want to keep this separate from selection mode, we could add a TabNavigationMode property (Horizontal/Vertical) on TableView , similar to how TapToEdit works. It would just be one extra check in HandleNavigations, no changes to GetNextSlot itself. Should we go with that, or do you think it should be handled differently?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get your point that in File Explorer, pressing the Tab key while editing a file name jumps to the next row. The key thing to note is that File Explorer only has one editable column and it's the Name column. So, TableView would behave exactly the same when there’s only one editable column in a row, jumping across rows with the Tab key.

Comment thread src/TableView.cs
do
{
newSlot = GetNextSlot(newSlot, shiftKey, e.Key is VirtualKey.Enter);
newSlot = GetNextSlot(newSlot, shiftKey, e.Key is VirtualKey.Enter || (e.Key is VirtualKey.Tab && SelectionUnit is TableViewSelectionUnit.Row));
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don’t think this change is necessary because the Tab key should always move to the next editable cell and put it in editing mode. If there’s no editable cell in the current row, it will automatically move to the next row.

Comment thread src/TableView.cs Outdated
{
SetIsEditing(false);
}
else if (SelectionUnit is TableViewSelectionUnit.Row or TableViewSelectionUnit.CellOrRow && newSlot.Row != currentCell.Slot.Row)
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use Cell.PrepareForEdit and Cell.EndEditing methods to control row highlighting.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, moved the highlight into Cell.PrepareForEdit and Cell.EndEditing since they fire for every editing trigger (tap, double-tap, keyboard, F2).

Comment thread src/TableView.cs Outdated

IsEditing = value;
UpdateCornerButtonState();

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From my testing, TableView doesn’t recycle the row when a cell is in edit mode. It could be a ListView behavior, but let’s keep it as is for now, and we don’t need to unhighlight the row once it’s highlighted.
On the other hand, Uno does recycle the row, but let’s not worry about that for now.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good to know that ListView doesn't recycle the row while a cell is in edit mode, that simplifies things. We've removed the highlight management from SetIsEditing completely. The highlight is now purely driven by PrepareForEdit/EndEditing, so once it's applied, it stays until the cell's EndEditing clears it. No intermediate toggle.

We've kept a defensive ApplyEditingHighlight(false) in PrepareContainerForItemOverride for recycled containers as-is for now. Since you mentioned recycling doesn't happen during edit, want us to remove it?

Comment thread src/TableViewRow.cs Outdated
TableView.CurrentRowIndex = Index;
TableView.LastSelectionUnit = TableViewSelectionUnit.Row;
}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we handle cell editing inside the cell, why do we need this code?

Copy link
Copy Markdown
Author

@rashmi-thakurr rashmi-thakurr Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We added this because we thought in Row mode, the row needed to catch the second tap (the tap-pause-tap like File Explorer rename) and forward it to the cell to start editing. But the cell already handles its own editing and now with the TapToEdit property guarding it in the cell's own OnTapped, the row doesn't need to be involved at all. Removed.

Comment thread src/TableViewRow.cs
Comment on lines +641 to +677
/// <summary>
/// Highlights or unhighlights the row to indicate that a cell is being edited.
/// </summary>
internal void ApplyEditingHighlight(bool isEditing)
{
_hasEditingHighlight = isEditing;
if (isEditing)
{
#if WINDOWS
if (RowPresenter is not null && _itemPresenter?.PointerOverBackground is { } pointerOverBrush)
{
RowPresenter.Background = pointerOverBrush;
}
#else
if (_selectionBackground is not null)
{
_selectionBackground.Opacity = 1;
}
#endif
}
else
{
#if WINDOWS
if (RowPresenter is not null)
{
RowPresenter.Background = _cellPresenterBackground;
}
#else
if (_selectionBackground is not null)
{
_selectionBackground.Opacity = IsSelected ? 1 : 0;
}
#endif
EnsureAlternateColors();
}
}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code block seems a bit off. I suggest adding an accent-tinted border or rectangle in the TableViewRowPresenter above the RootPanel, and controlling its visibility from the code-behind. For that, you can use the Cell.PrepareForEdit and Cell.EndEditing methods.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, that code was a bit off. What we were trying to do was mimic the pointer-over look by directly swapping the row's background when editing started and restoring it when done. The problem was it kept clashing with EnsureAlternateColors (we had to add a guard to stop it from overwriting the highlight), and we needed #if WINDOWS branching because Uno handles it differently.

So we went with your suggestion, added a Border overlay in TableViewRowPresenter.xaml sitting above the RootPanel, hit-test invisible, collapsed by default. The code-behind just toggles its visibility. Much cleaner since the highlight is now completely separate from the row's background, no guards, no platform branching. We added a TableViewRowEditingHighlightBackground theme resource in Resources.xaml for Light, Dark and HighContrast. And the visibility is driven from PrepareForEdit/EndEditing as you suggested.

Comment thread src/TableViewRow.cs Outdated

if (e.Handled) { base.OnDoubleTapped(e); return; }

if (TableView?.SelectionUnit is TableViewSelectionUnit.Row
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we handle cell editing inside the cell, why do we need this code?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the cell already handles double-tap editing on its own. We added this thinking the row needed to be in charge of the whole flow, find the tapped cell, select it, start editing, and apply the highlight, all in one place. But the cell already knows how to edit itself, so the row was just doing the cell's job for it. Removed.

Comment thread src/TableViewCell.cs Outdated
MakeSelection();
e.Handled = true;
}
else if (TableView?.SelectionUnit is TableViewSelectionUnit.CellOrRow
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add a bool TapToEdit property to TableView, and only enable cell edit mode on tap when this property is true, regardless of the SelectionUnit setting.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, added a TapToEdit bool DP on TableView, defaults to false. When true, tapping an already-selected cell starts editing regardless of SelectionUnit.

@w-ahmad
Copy link
Copy Markdown
Owner

w-ahmad commented Apr 13, 2026

Thank you for your contribution @rashmi-thakurr! I’ve left some feedback in the review to help improve things. Let me know if you’d like clarification on any of the points.

@rashmi-thakurr
Copy link
Copy Markdown
Author

Thanks for the thorough review, @w-ahmad Really appreciate the feedback - it pushed the implementation in a much cleaner direction.

Here's what we've updated:

  • Replaced the background swap with a XAML overlay in TableViewRowPresenter , way cleaner, no more fighting with EnsureAlternateColors or platform branching.
  • Moved the highlight into PrepareForEdit/EndEditing, covers all editing triggers naturally instead of wiring it up in multiple places.
  • Removed the tap/double-tap forwarding from Row, the cell already handles its own editing, so the row was just doing the cell's job. Gone now.
  • Added a TapToEdit bool property on TableView , defaults to false, guards the tap-pause-tap behavior in the cell's OnTapped. Double-tap stays unguarded.
  • Kept a defensive highlight reset in PrepareContainerForItemOverride for now, but since you mentioned recycling doesn't happen during edit, happy to remove it if you'd rather keep things minimal.

One thing we'd love your input on, we currently make Tab wrap to the next row in Row mode (like File Explorer). Would you prefer we make this configurable with something like a TabNavigationMode property, or keep Tab horizontal-only? Let us know!

@w-ahmad
Copy link
Copy Markdown
Owner

w-ahmad commented Apr 16, 2026

Thanks for the updates @rashmi-thakurr! I tested your new changes and noticed that when a cell exits edit mode, the row shifts slightly to the left. I’m not sure about the reason, but this newly added border needs to be rearranged, similar to how we handle the root panel and other elements of the row presenter.

Screen.Recording.2026-04-16.200644.mp4

I'm not great at UI design, but I suggest using a border with rounded corners, 1px border thickness and a slightly accent-tinted background to highlight the row. Here's a demo of what I mean...

<!--TODO: put these property values to the theme resources-->
<Border BorderThickness="1"
        CornerRadius="{ThemeResource ControlCornerRadius}"
        BorderBrush="{ThemeResource AccentFillColorDefaultBrush}">
    <Border.Background>
        <SolidColorBrush Color="{StaticResource SystemAccentColor}"
                         Opacity="0.2" />
    </Border.Background>
</Border>
Screen.Recording.2026-04-16.201550.mp4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Select Row Automatically When Editing a Cell

2 participants