Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,27 @@ to land under these conventions; subsequent specs follow this shape.

### Fixed

- **`DropDownButton` / `SplitButton` / `ToggleSplitButton` `.Flyout` now
reconciles across re-renders.** Mount built each button's flyout once
and the corresponding Update paths never rebuilt it, so any dynamic
flyout content (a `MenuFlyoutContentElement` whose `Items` array is
state-derived, a `ContentFlyoutElement` whose subtree depends on
state, or a swapped flyout instance entirely) froze at first-mount
values. The matching X→null transition (a button whose flyout is
removed across renders) also left the stale flyout attached.
`UpdateDropDownButton`, `UpdateSplitButton`, and
`UpdateToggleSplitButton` now thread the old element +
`requestRerender` and call the existing `ApplyFlyoutAttachment`
helper, which already knows how to reuse the realized `FlyoutBase`
(so an already-open flyout stays open), clear+repopulate
`MenuFlyout.Items`, or reconcile content inside a `Flyout.Content`
child; an explicit `Flyout = null` branch handles the clear case.
Same class of bug as the recently-fixed CommandBar / TeachingTip
Content gap (microsoft-ui-reactor#343). Adds `FlyoutReconcileFixtures`
(six selftests covering text mutation, count mutation,
`ContentFlyoutElement` subtree mutation, and X→null clearing across
the three button kinds).

- **ListView / GridView / LazyVStack / LazyHStack now surface incremental
WinUI deltas for keyed updates.** Previously, any `ItemCount` change
rebuilt `ItemsSource` from `Enumerable.Range(...)`, which caused WinUI
Expand Down
26 changes: 19 additions & 7 deletions src/Reactor/Core/Reconciler.Update.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,12 @@ public sealed partial class Reconciler
=> UpdateRepeatButton(o, n, rb),
(ToggleButtonElement o, ToggleButtonElement n, WinPrim.ToggleButton tb)
=> UpdateToggleButton(o, n, tb),
(DropDownButtonElement, DropDownButtonElement n, WinUI.DropDownButton ddb)
=> UpdateDropDownButton(n, ddb),
(DropDownButtonElement o, DropDownButtonElement n, WinUI.DropDownButton ddb)
=> UpdateDropDownButton(o, n, ddb, requestRerender),
(SplitButtonElement o, SplitButtonElement n, WinUI.SplitButton sb)
=> UpdateSplitButton(o, n, sb),
=> UpdateSplitButton(o, n, sb, requestRerender),
(ToggleSplitButtonElement o, ToggleSplitButtonElement n, WinUI.ToggleSplitButton tsb)
=> UpdateToggleSplitButton(o, n, tsb),
=> UpdateToggleSplitButton(o, n, tsb, requestRerender),
(RichEditBoxElement o, RichEditBoxElement n, WinUI.RichEditBox reb)
=> UpdateRichEditBox(o, n, reb),
(TextFieldElement o, TextFieldElement n, TextBox tb)
Expand Down Expand Up @@ -736,24 +736,32 @@ private static void RebuildRichTextBlocks(RichTextBlockElement n, WinUI.RichText
return null;
}

private UIElement? UpdateDropDownButton(DropDownButtonElement n, WinUI.DropDownButton ddb)
private UIElement? UpdateDropDownButton(DropDownButtonElement o, DropDownButtonElement n, WinUI.DropDownButton ddb, Action requestRerender)
{
if (ddb.Content as string != n.Label) ddb.Content = n.Label;
SetElementTag(ddb, n);
if (n.Flyout is not null)
ApplyFlyoutAttachment(ddb, o.Flyout, n.Flyout, requestRerender);
else if (o.Flyout is not null)
ddb.Flyout = null;
Comment on lines +743 to +746
ApplySetters(n.Setters, ddb);
return null;
}

private UIElement? UpdateSplitButton(SplitButtonElement o, SplitButtonElement n, WinUI.SplitButton sb)
private UIElement? UpdateSplitButton(SplitButtonElement o, SplitButtonElement n, WinUI.SplitButton sb, Action requestRerender)
{
sb.Content = n.Label; SetElementTag(sb, n);
if (o.OnClick is null && n.OnClick is not null)
sb.Click += (s, _) => (GetElementTag((UIElement)s!) as SplitButtonElement)?.OnClick?.Invoke();
if (n.Flyout is not null)
ApplyFlyoutAttachment(sb, o.Flyout, n.Flyout, requestRerender);
else if (o.Flyout is not null)
sb.Flyout = null;
Comment on lines +756 to +759
ApplySetters(n.Setters, sb);
return null;
}

private UIElement? UpdateToggleSplitButton(ToggleSplitButtonElement o, ToggleSplitButtonElement n, WinUI.ToggleSplitButton tsb)
private UIElement? UpdateToggleSplitButton(ToggleSplitButtonElement o, ToggleSplitButtonElement n, WinUI.ToggleSplitButton tsb, Action requestRerender)
{
SetElementTag(tsb, n);
if (o.OnIsCheckedChanged is null && n.OnIsCheckedChanged is not null)
Expand All @@ -769,6 +777,10 @@ private static void RebuildRichTextBlocks(RichTextBlockElement n, WinUI.RichText
ChangeEchoSuppressor.BeginSuppress(tsb);
tsb.IsChecked = n.IsChecked;
}
if (n.Flyout is not null)
ApplyFlyoutAttachment(tsb, o.Flyout, n.Flyout, requestRerender);
else if (o.Flyout is not null)
tsb.Flyout = null;
Comment on lines +780 to +783
ApplySetters(n.Setters, tsb);
return null;
}
Expand Down
Loading
Loading