Skip to content

Commit fa843ab

Browse files
committed
persist row details expanded state per item
1 parent b225cd7 commit fa843ab

3 files changed

Lines changed: 54 additions & 13 deletions

File tree

src/TableView.Properties.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System;
77
using System.Collections.Generic;
88
using System.Linq;
9+
using System.Runtime.CompilerServices;
910
using System.Threading.Tasks;
1011

1112
namespace WinUI.TableView;
@@ -359,6 +360,8 @@ public bool ShowFilterItemsCount
359360
/// </summary>
360361
internal bool IsEditing { get; private set; }
361362

363+
internal ConditionalWeakTable<object, TValue<bool>> DetailsPaneStates { get; } = [];
364+
362365
/// <summary>
363366
/// Gets or sets the filter handler for the TableView.
364367
/// </summary>

src/TableView.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ protected override void PrepareContainerForItemOverride(DependencyObject element
109109
{
110110
row.EnsureCellsStyle(default, item);
111111
row.ApplyCellsSelectionState();
112+
row.RowPresenter?.ApplyDetailsPaneState(item);
112113

113114
if (CurrentCellSlot.HasValue)
114115
{
@@ -667,6 +668,8 @@ private static TableViewBoundColumn GetTableViewColumnFromType(string? propertyN
667668
/// </summary>
668669
private void ItemsSourceChanged(DependencyPropertyChangedEventArgs e)
669670
{
671+
DetailsPaneStates.Clear();
672+
670673
using var defer = _collectionView.DeferRefresh();
671674
_collectionView.Source = null!;
672675

src/TableViewRowPresenter.cs

Lines changed: 48 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using Microsoft.UI.Xaml.Controls;
44
using Microsoft.UI.Xaml.Controls.Primitives;
55
using Microsoft.UI.Xaml.Data;
6+
using Microsoft.UI.Xaml.Input;
67
using Microsoft.UI.Xaml.Media;
78
using Microsoft.UI.Xaml.Shapes;
89
using System;
@@ -13,6 +14,26 @@
1314

1415
namespace WinUI.TableView;
1516

17+
internal class TValue<T> where T : struct
18+
{
19+
public TValue(T value)
20+
{
21+
Value = value;
22+
}
23+
24+
public T Value { get; }
25+
26+
public static implicit operator T(TValue<T> value)
27+
{
28+
return value.Value;
29+
}
30+
31+
public static implicit operator TValue<T>(T value)
32+
{
33+
return new(value);
34+
}
35+
}
36+
1637
/// <summary>
1738
/// Represents a control that presents visuals for the <see cref="WinUI.TableView.TableViewRow"/>.
1839
/// </summary>
@@ -68,8 +89,7 @@ protected override void OnApplyTemplate()
6889

6990
if (_detailsToggleButton is not null)
7091
{
71-
_detailsToggleButton.Checked += OnDetailsToggleButtonChecked;
72-
_detailsToggleButton.Unchecked += OnDetailsToggleButtonUnChecked;
92+
_detailsToggleButton.Tapped += OnDetailsToggleButtonTapped;
7393
}
7494

7595
if (_detailsPanel is not null)
@@ -190,11 +210,8 @@ internal void SetRowDetailsVisibility()
190210
}
191211
else if (mode is TableViewRowDetailsVisibilityMode.VisibleWhenSelected)
192212
{
193-
if (_detailsToggleButton is not null)
194-
_detailsToggleButton.IsChecked = TableViewRow?.IsSelected ?? false;
195-
else
196-
VisualStates.GoToState(this, false, (TableViewRow?.IsSelected ?? false) ? VisualStates.StateDetailsVisible : VisualStates.StateDetailsCollapsed);
197-
213+
var state = (TableViewRow?.IsSelected ?? false) ? VisualStates.StateDetailsVisible : VisualStates.StateDetailsCollapsed;
214+
VisualStates.GoToState(this, false, state);
198215
VisualStates.GoToState(this, false, VisualStates.StateDetailsButtonCollapsed);
199216
}
200217
else if (mode is TableViewRowDetailsVisibilityMode.VisibleWhenExpanded)
@@ -209,19 +226,37 @@ internal void SetRowDetailsVisibility()
209226
}
210227

211228
/// <summary>
212-
/// Handles the Checked event of the details toggle button.
229+
/// Handles the Tapped event of the details toggle button.
213230
/// </summary>
214-
private void OnDetailsToggleButtonChecked(object sender, RoutedEventArgs e)
231+
private void OnDetailsToggleButtonTapped(object sender, TappedRoutedEventArgs e)
215232
{
216-
VisualStates.GoToState(this, false, VisualStates.StateDetailsVisible);
233+
ToggleDetailsPane(TableViewRow?.Content, _detailsToggleButton!.IsChecked ?? false);
217234
}
218235

219236
/// <summary>
220-
/// Handles the Unchecked event of the details toggle button.
237+
/// Toggles the visibility of the details pane.
221238
/// </summary>
222-
private void OnDetailsToggleButtonUnChecked(object sender, RoutedEventArgs e)
239+
private void ToggleDetailsPane(object? content, bool isVisible)
223240
{
224-
VisualStates.GoToState(this, false, VisualStates.StateDetailsCollapsed);
241+
if (TableView is null || content is null) return;
242+
243+
TableView.DetailsPaneStates.AddOrUpdate(content, isVisible);
244+
var state = isVisible ? VisualStates.StateDetailsVisible : VisualStates.StateDetailsCollapsed;
245+
VisualStates.GoToState(this, false, state);
246+
}
247+
248+
/// <summary>
249+
/// Ensures that the details pane visibility is synchronized for the specified item when row.
250+
/// </summary>
251+
internal void ApplyDetailsPaneState(object? item)
252+
{
253+
if (TableView?.RowDetailsVisibilityMode is TableViewRowDetailsVisibilityMode.VisibleWhenExpanded &&
254+
_detailsToggleButton is not null && TableView is not null && item is not null)
255+
{
256+
var isChecked = TableView.DetailsPaneStates.TryGetValue(item, out var value) ? value.Value : false;
257+
_detailsToggleButton!.IsChecked = isChecked;
258+
ToggleDetailsPane(item, isChecked);
259+
}
225260
}
226261

227262
/// <summary>

0 commit comments

Comments
 (0)