Visitar URL original
fix(tooltip): Keep the popup panel as parent while a ToolTip is open by mikernet · Pull Request #24592 · unoplatform/uno · GitHub
Skip to content

fix(tooltip): Keep the popup panel as parent while a ToolTip is open - #24592

Merged
13 commits merged into
unoplatform:masterfrom
mikernet:dev/mikernet/tooltip-image-pending
Nov 5, 2026
Merged

13 commits merged into
unoplatform:masterfrom
mikernet:dev/mikernet/tooltip-image-pending

Conversation

@mikernet

@mikernet mikernet commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

GitHub Issue: closes #24557, closes #24820

PR Type:

🐞 Bugfix

What changed? 🚀

On Skia, an Image inside an open ToolTip stayed blank when its bitmap arrived after the tooltip opened, and only showed the next time the tooltip opened.

The bitmap is applied during measure, and Image.InvalidateMeasure() reaches the layout root by walking the parent chain. When a ToolTip opens, AttachToPopup added it to the popup panel and then reset its parent to the previous value, which is null for a tooltip set through ToolTipService. The dirty path therefore stopped at the tooltip: the image kept its measure-dirty flag, the popup panel was never flagged, and no layout pass reached the image until the tooltip was opened again and measured from scratch. Verified by dumping the chain at the point of failure:

Image dirty=True -> ContentPresenter path=True -> ToolTip path=True -> (null)   PopupPanel dirty=False

The parent was reset to keep the popup panel's own DataContext from replacing the one the owner provides through ToolTipService.ToolTip (that attached property has ValueInheritsDataContext, which no longer forwards changes once the value is parented elsewhere).

The tooltip now stays parented to the popup panel while it is showing and is detached again when it closes, so the closed state is unchanged. To keep the DataContext behavior:

  • the owner-provided DataContext is re-applied right after parenting (parenting inherits the panel's DataContext first), and
  • the owner's DataContextChanged is forwarded to the tooltip while it is open, alongside the existing ActualThemeChanged subscription. The elements that were subscribed are kept, so closing unsubscribes from those even if the tooltip has been set on another element in the meantime.

While closed, the tooltip needs no forwarding: it is again a value of the owner's ToolTipService.ToolTip, whose default metadata (ValueInheritsDataContext) pushes the owner's DataContext changes to it. WinUI's ToolTip has no DataContextChanged handler; that an open WinUI tooltip follows its owner's changes comes from the WinUI probe in the review, and the two DataContext tests below pass on native WinUI as well.

The same broken parent chain is behind #24820, where an ItemsControl inside the tooltip creates its containers after the first measure and the tooltip stays an empty border on its first open.

DataContext follow-ups

Comparing against native WinUI surfaced two DataContext differences (see the review discussion), both now addressed:

  • Closing no longer drops the DataContext. Detaching from the popup panel clears the inherited values, and the owner only pushes its DataContext again when it changes, so the closed tooltip's bindings resolved to null after every hover. The value is now kept across the detach, as on WinUI and on master. Only the inherited value is carried across, so a DataContext set or bound on the tooltip itself stays on top of it and doesn't leak into it.
  • The DataContext comes from the owner, not the placement target. ToolTipService handed the tooltip a single element (the PlacementTarget when set, else the owner) for both positioning and DataContext, so a tooltip with a placement target opened with the target's DataContext and, with the forwarding added here, followed it entirely. The tooltip now keeps the owner (the element the tooltip is set on) separately from the placement anchor and takes its DataContext from the owner, as ToolTip::SetContainer does in WinUI. The placement target only positions the tooltip.

The popup also releases the tooltip when it closes, as ToolTip::Close does in WinUI, so Parent is null while closed instead of the Popup. Assigning and clearing Popup.Child is what sets and clears the tooltip's parent, so the tooltip no longer calls SetParent itself.

Tests

New Given_ToolTip runtime tests:

The first five fail on master's ToolTip (except as noted) and pass with this PR; their expected values mirror the native WinUI probe results posted in the review, and all of them except the bound-DataContext test pass on native WinUI too (Given_ToolTip run on the WinAppSDK SamplesApp head; that test is excluded there, since WinUI writes the owner's DataContext over a binding on the tooltip when the owner's changes; When_Closed_Then_Parent_Cleared waits for the parent to clear, since WinUI's popup releases the tooltip only after the Closed transition). Validation on Skia desktop: Given_ToolTip, Given_Slider, Given_Image, Given_Popup, Given_ElementTheme, Given_Control, Given_DragView, Given_FrameworkElement_And_Leak, Given_PropertyPathListener, KeyboardAcceleratorTests and TabViewTests all pass (371 tests, 11 skipped), including the four DataContext-tracking tooltip tests that guard the reason the parent used to be reset.

PR Checklist ✅

When a ToolTip opened, it was added to the popup panel and its parent
was then reset to what it was before, which is null for a tooltip set
through ToolTipService. Layout invalidations from the tooltip content
walk the parent chain to reach the layout root, so they stopped at the
tooltip: an Image whose bitmap arrived after the tooltip opened kept
its measure-dirty flag and stayed blank until the tooltip was opened
again and measured from scratch.

The tooltip now stays parented to the popup panel while it is showing
and leaves it when it closes. The parent was reset to keep the panel's
DataContext from replacing the one the owner provides through
ToolTipService.ToolTip, so that value is re-applied after parenting and
the owner's DataContextChanged is forwarded while open.

Fixes unoplatform#24557
Copilot AI lite review requested due to automatic review settings September 23, 2026 00:05

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Unresolved popup-parenting and DataContext handling issues remain.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 2 Medium severity

Open (2)
What changed in this PR

Fixes tooltip image loading by keeping open tooltips attached to the popup panel and preserving owner DataContext behavior.

Changes:

  • Updates tooltip popup parenting and data-context forwarding.
  • Adds regression coverage for deferred image loading.
File Summary
src/​Uno.UI/​UI/​Xaml/​Controls/​ToolTip/​ToolTip.cs Updates popup attachment, detachment, and data-context handling.
src/​Uno.UI.RuntimeTests/​Tests/​Windows_UI_Xaml_Controls/​Given_ToolTip.cs Adds deferred image-loading tooltip coverage.

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Popup.Child sets the logical parent override, so the public Parent is
the popup after the first open and the actual parent must drive the
attach. The owner DataContext is read before joining the popup panel,
whose own DataContext is inherited on parenting.
Copilot AI review requested due to automatic review settings September 23, 2026 00:16

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

Preserve or reapply the owner’s DataContext when detaching the tooltip.

Review effort: Lite
Findings: None

Resolved since last review (2)

@MartinZikmund

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@unodevops

Copy link
Copy Markdown
Contributor

🤖 Your WebAssembly Skia Sample App stage site is ready! Visit it here: https://unowasmprstaging.z20.web.core.windows.net/pr-24592/wasm-skia-net9/index.html

@nventive-devops

Copy link
Copy Markdown
Contributor

The build 235198 found UI Test snapshots differences: skia-linux-screenshots: 57, skia-windows-screenshots: 2310, wasm: 11

Details
  • skia-linux-screenshots: 57 changed over 2348

    🚨🚨 Comparison Details (first 20) 🚨🚨
    • ButtonClippingTestsControl.png-dark
    • ButtonClippingTestsControl.png
    • Buttons.png-dark
    • Buttons.png
    • CalendarView_Theming.png-dark
    • CalendarView_Theming.png
    • ClipboardTests.png-dark
    • DisplayInformation.png-dark
    • DropDownButtonPage.png-dark
    • DropDownButtonPage.png
    • ContextRequested.png-dark
    • ContextRequested.png
    • ElementLevelTheme.png-dark
    • ElementLevelTheme.png
    • Examples.png-dark
    • Examples.png
    • ExpanderColorValidationPage.png-dark
    • ExpanderColorValidationPage.png
    • Focus_FocusVisual_Properties.png-dark
    • ImageIconPage.png-dark
  • skia-windows-screenshots: 2310 changed over 2440

    🚨🚨 Comparison Details (first 20) 🚨🚨
    • Arrange_Performance01.png-dark
    • Attributed_text_Supserscript.png
    • AutoBorderStretchwithrightmargin.png
    • AutomationProperties_Name.png-dark
    • AutoSuggestBox_BitmapIcon.png
    • AutoSuggestBox_Keyboard.png-dark
    • BackGesture.png
    • BasicAutoSuggestBox.png
    • Basics Pivot Test.png-dark
    • Basics Pivot Test.png
    • BasicThemeResources.png-dark
    • BasicThemeResources.png
    • BitmapIcon_Monochromatic.png-dark
    • BitmapIcon_Monochromatic.png
    • BorderCenteredwithmargins.png-dark
    • BorderCenteredwithmargins.png
    • BorderRightwithmargins.png-dark
    • BorderRightwithmargins.png
    • Border_AntiAlias.png-dark
    • Border_AntiAlias.png
  • wasm: 11 changed over 1076

    🚨🚨 Comparison Details (first 20) 🚨🚨
    • UITests.Shared.Microsoft_UI_Xaml_Controls.ExpanderTests.WinUIExpanderPage
    • UITests.Shared.Windows_UI_Xaml_Controls.MediaPlayerElement.MediaPlayerElement_Minimal
    • UITests.Shared.Windows_UI_Xaml_Controls.MediaPlayerElement.MediaPlayerElement_Ogg_Extension
    • SamplesApp.Wasm.Windows_UI_Xaml_Controls.ListView.ListView_IsSelected
    • SamplesApp.Windows_UI_Xaml_Controls.ListView.ListViewSelectedItems
    • UITests.Microsoft_UI_Xaml_Controls.WebView2Tests.WebView2_NavigationProperties
    • SamplesApp.Microsoft_UI_Xaml_Controls.WebView2Tests.WebView2_EnableDevTools
    • UITests.Uno_Web.Http.CookieManagerTests
    • UITests.Windows_UI_Xaml_Controls.CalendarView.CalendarView_Theming
    • UITests.Windows_UI_Xaml_Media_Animation.ColorAnimation_Background
    • Uno.UI.Samples.Content.UITests.WebView.WebView_AnchorNavigation

@Xiaoy312 Xiaoy312 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for this, it also fixes #24820 (same root cause, ItemsControl content instead of an Image). I compared the DataContext behavior against native WinUI and found two differences from WinUI. Both come from the parenting and DataContext changes.

The same probe code ran on native WinUI (standalone unpackaged app, WinAppSDK 1.7.250606001) and on Uno Skia desktop, with master's ToolTip.cs and with this PR's (eb38bcbb84).

1. The tooltip loses its DataContext on close

The owner's DataContext is set after SetToolTip; the tooltip is then opened and closed twice, and the owner's DataContext changes in between. The tooltip content is a TextBlock bound to {Binding}.

Step WinUI Uno master This PR
open #1 VM1 VM1 VM1
closed #1 VM1 (text kept) VM1 null (text empty)
closed, owner changes to VM2 VM2 VM2 VM2
open #2, owner changes to VM3 VM3 VM3 VM3
closed #2 VM3 VM3 null

DetachFromPopup calls SetParent(null), and changing the parent clears every value inherited from it, DataContext included (DependencyObject.Store Parent setter → CleanupInheritedProperties). Nothing puts it back: the owner only pushes its DataContext when that DataContext changes. So every hover now flips the tooltip's subtree between null and the view model. Bindings re-run, converters are handed null, and an ItemsControl in the tooltip clears and rebuilds its items. WinUI and master keep the DataContext while closed.

Suggested fix: in DetachFromPopup, capture DataContext before SetParent(null) and set it back afterwards at Inheritance precedence, as AttachToPopup does when opening.

2. With ToolTipService.PlacementTarget, the tooltip follows the placement target

The owner's DataContext is Owner and the placement target's is Target.

Step WinUI Uno master This PR
open Owner Target Target
owner changes to Owner2 while open Owner2 Owner2 Target
target changes to Target2 while open Owner2 (ignored) Owner2 Target2
closed Owner2 Owner2 null

WinUI takes the tooltip's DataContext from the owner (ToolTip::SetContainer). The placement target is only used for positioning and flow direction. Uno stores the placement target as the tooltip's _owner (toolTip.SetAnchor(GetPlacementTarget(container) ?? container) in ToolTipService.RegisterToolTip). So master already opens with the wrong DataContext, but after that it follows the real owner. This PR subscribes OnOwnerDataContextChanged to that same _owner. Because the owner's own changes no longer reach a tooltip parented to the popup panel, the tooltip now follows the placement target entirely.

The root cause is older than this PR. But since this PR adds the forwarding, it would help if ToolTip kept the owner separately from the placement anchor, and took its DataContext from the owner (both the "propagate the DC once" on open and the new DataContextChanged forwarding).

3. The tooltip's parents: closer to WinUI

For reference, the parenting change itself moves Uno toward WinUI.

WinUI Uno master This PR
Open: VisualTreeHelper.GetParent(toolTip) popup root (Canvas) null PopupRoot
Open: toolTip.Parent Popup Popup Popup
Open: walking up from the tooltip's content ContentPresenter > ToolTip > Canvas > null ContentPresenter > ToolTip > null ContentPresenter > ToolTip > PopupRoot > XamlIslandRoot > null
Closed: VisualTreeHelper.GetParent(toolTip) / toolTip.Parent null / null null / Popup null / Popup

An open WinUI tooltip has the popup root as its visual parent, and so does this PR; master has none, which is the gap behind both #24557 and #24820. One small difference remains in both Uno versions: WinUI clears Popup.Child when the tooltip closes (ToolTip::Close), so Parent goes back to null, while Uno keeps Popup. Nothing here needs to change for this PR.

Copilot AI lite review requested due to automatic review settings September 30, 2026 16:13

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

Reapply the owner’s DataContext after detachment and add the issue-tracking attribute to the regression test.

Review effort: Lite
Findings: None

Copilot AI lite review requested due to automatic review settings September 30, 2026 17:03

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟢 Approval recommended

No unresolved issues were identified that would block approval.

Review effort: Lite
Findings: None

@mikernet

mikernet commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor Author

For a servicing/6.8 backport: ported onto the 6.8.0-dev.212 commit at Singulink@47830b3d54 (branch Singulink:custom/6.8). One difference: 6.8 gates the owner theme-change subscription behind UNO_HAS_ENHANCED_LIFECYCLE, so the owner DataContextChanged forwarding got its own unconditional subscribe/unsubscribe pair; all five tests pass on Skia desktop.

mikernet added a commit to mikernet/uno that referenced this pull request Oct 9, 2026
…ver it closed (port)

Port of 9d414ec (stacked on unoplatform#24592). As in WinUI's
ToolTip::OnIsOpenChanged, the ToolTip tells the service when it has
closed, and the service drops it if it is still the current one, so a
tooltip closed by a path the service does not drive (its popup closed
with the other popups, or the app setting IsOpen) is not kept.

6.8 differences: the call sits after UnsubscribeOwnerDataContextChanged
in ToolTip.OnOpenChanged (6.8's shape of unoplatform#24592), and the tests live in
Tests/Windows_UI_Xaml_Controls. This branch also carries the unoplatform#25102 port,
so the owner is already collected once it unloads; the service-state
test is the one that fails without this change here.
The tooltip tests closed their popups in finally but left their owner as the
window content, so the visual tree outlived the test.
Copilot AI lite review requested due to automatic review settings October 9, 2026 03:45

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

No unresolved issues were identified that would block approval.

0 open findings

🧠 Review effort: Lite

mikernet added a commit to mikernet/uno that referenced this pull request Oct 9, 2026
…platform#25137 after review

The unoplatform#24592 tooltip tests reset the window content in finally (ca34dc1).
The unoplatform#25137 tests follow e7496a8: compiled on every head and skipped on
native WinUI with PlatformCondition instead of #if HAS_UNO, popups closed
through the public VisualTreeHelper.GetOpenPopupsForXamlRoot, and a new
test for a tooltip whose opening is cancelled during the show delay.

The source side of e7496a8 is already on this branch: the ToolTip
close notification (3cfe072) and the service-side clears it carries
from unoplatform#25102 (800247f).

@morning4coffe-dev morning4coffe-dev left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Verified: diff of ToolTip.cs, ToolTipService.cs and Given_ToolTip.cs at head ca34dc1, the review thread (including the WinUI probe tables), and the WinUI source: ToolTip_Partial.cpp SetContainer (L72-87), OpenPopup (L573-611), Close (L666-690); ToolTipService_Partial.cpp RegisterToolTip (L153-154), container resolution on pointer enter (L631-634), unregister (L288-289). Uno side: Popup.WithPopupRoot.cs (L26-30), ToolTipService.Properties.cs (default FrameworkPropertyMetadata). Not built or run. Runtime results are author-reported (Skia desktop only). CI rollup shows no failing checks; no Azure runtime test check appears in the rollup.

Findings (by severity):

  1. Medium - ToolTip.cs:234-236 and ToolTip.cs:248-250. The owner DataContextChanged handler is subscribed and unsubscribed through GetDataContextOwner(), which reads _container at each call. _container is set in SetContainer (ToolTipService.cs:48) and never cleared; UnregisterToolTip does not call SetContainer(null) (WinUI does, ToolTipService_Partial.cpp:289). If the same ToolTip is registered against another container while it is open, Close unsubscribes the new container and leaves the handler on the old one, so a closed tooltip keeps receiving DataContext writes. Suggested fix: keep the element that was subscribed in a field and unsubscribe from that field.

  2. Low - ToolTip.cs:194 (SetParent(Popup.PopupPanel)) and ToolTip.cs:215 (SetParent(null)). Popup.Child assignment already adds and removes the child in PopupPanel.Children (Popup.WithPopupRoot.cs:26-30), so these writes appear redundant. Not wrong, but the comments imply they are load-bearing. Either drop them or state what they guard.

  3. Low - Parity source gap. WinUI's ToolTip has no DataContextChanged subscription (ToolTip_Partial.cpp has no such handler); it snapshots the container DataContext in SetContainer. The forwarding added here (ToolTip.cs:254-259) is what makes owner changes visible while open, and the review probe table reports WinUI doing the same. The parity for that behavior rests on the probe, not on the source. A code comment citing the probe, or the test comment, would make this checkable.

  4. Note - closed-state DataContext. The PR's "closed tooltip keeps its DataContext" and "owner change while closed reaches it" depend on ToolTipService.ToolTip's default metadata (ValueInheritsDataContext is the default, FrameworkPropertyMetadataOptions.cs:81), not on the forwarding, which is unsubscribed on close. I read this from source; the PR body does not explain it. Worth one sentence in the PR or a code comment.

Not validated by me: runtime behavior of all five new Given_ToolTip tests (author reports Skia desktop pass and fail-before on master); WASM, Android, iOS; the image-load test asset availability on other targets.

The owner's DataContextChanged and ActualThemeChanged were subscribed on
open and unsubscribed on close through the container and the anchor,
which are read again each time. When the tooltip is set on another
element while it is open, both change in between, so closing unsubscribed
from the new element and left the handlers on the first one for good: it
kept writing its DataContext into the tooltip even after the tooltip was
removed from it. Keep the elements that were subscribed and unsubscribe
from those.
Since the popup lets go of the tooltip on close, every open assigns
Popup.Child afresh, and the popup adds its child to the popup panel and
removes it again, which sets and clears the tooltip's parent. The explicit
SetParent calls and the guard around the Popup.Child assignment no longer
did anything.
The closed tooltip gets its owner's DataContext changes from
ToolTipService.ToolTip's default metadata (ValueInheritsDataContext), and
the parity of forwarding them while open rests on WinUI's behavior rather
than on its source, which has no such handler: the DataContext tests run
on native WinUI and pass there. Say both where they apply.
On native WinUI the popup lets go of the tooltip only once the Closed
visual transition has played (ToolTip::Close runs when its storyboard
completes), so When_Closed_Then_Parent_Cleared failed there right after
WaitForIdle. Wait for the parent to clear instead; Uno releases it as soon
as the tooltip closes.
Copilot AI lite review requested due to automatic review settings October 16, 2026 12:17
@mikernet

Copy link
Copy Markdown
Contributor Author

@morning4coffe-dev, by finding:

  1. Fixed in 0994593. Confirmed: if the tooltip is set on a second element while it is open, closing unsubscribed through the new container and left the handler on the first owner for good, so the first owner kept writing its DataContext into the tooltip even after the tooltip was removed from it. The ActualThemeChanged subscription next to it, from master, had the same pattern with the anchor. Both subscribed elements are now kept in fields, and closing unsubscribes from those. New test When_Moved_To_Another_Owner_While_Open_Then_Former_Owner_Not_Followed fails without the change and passes with it, on native WinUI as well.
    I did not add SetContainer(null) to UnregisterToolTip. WinUI clears the owner and the container together there (SetOwner(NULL), then SetContainer(NULL), which also nulls the tooltip's DataContext), while Uno's unregister has never cleared the anchor (SetAnchor is public and takes an element). Clearing only the container would make the anchor, which is the placement target when there is one, the DataContext source again: the difference Xiaoy312 found. The close path no longer reads _container or the anchor, and the next RegisterToolTip overwrites both.
  2. Dropped in bd13144. They were load-bearing before 524dd16, when Popup.Child stayed set across a close and the reopen had to restore the parent. Since the popup lets go of the tooltip on close, every open assigns Popup.Child afresh, and adding the child to PopupPanel.Children and removing it again sets and clears the parent (Popup.OnChildChangedPartialNative, UIElement.AddChild, UIElementCollection.Remove). LogicalParentOverride is set and cleared by the Popup.Child change itself (Popup.OnChildChangedPartial), not by SetParent. The guard around the Popup.Child assignment went with them. When_Closed_Then_Parent_Cleared and the reopen in When_Image_Source_Loads_While_Open pass without them.
  3. 94e4f41: OnOwnerDataContextChanged now says that WinUI's ToolTip has no such handler, and the two DataContext tests say their expected values are WinUI's. They are not excluded on native WinUI, so the parity no longer rests on the probe alone: I ran Given_ToolTip on the WinAppSDK SamplesApp head, and all of this PR's tests pass there. That run also caught When_Closed_Then_Parent_Cleared asserting too early on WinUI, where the popup releases the tooltip only after the Closed transition has played; d62ceb9 waits for it.
  4. Added in 94e4f41, in DetachFromPopup's comment, and in the PR body: while closed, the owner's DataContext changes reach the tooltip through ToolTipService.ToolTip's default metadata (ValueInheritsDataContext), not through the forwarding.

@Xiaoy312, both DataContext differences from your probe were addressed in 427c457 (When_Closed_Then_DataContext_Kept, When_PlacementTarget_Then_DataContext_From_Owner, both passing on native WinUI as well), and 524dd16 releases the popup child on close, so Parent is null while closed, as on WinUI. #24820 is covered by f0d86ec (When_Content_Realizes_On_Load_Then_Measured_On_First_Open), and the PR closes it too.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

Tooltip owner subscription handling can leave stale handlers and misroute DataContext updates.

0 open findings

🧠 Review effort: Lite

AttachToPopup and DetachFromPopup carried the tooltip's DataContext across
the parent change by reading DataContext, the effective value, and writing
it back at Inheritance precedence. A DataContext set or bound on the
tooltip itself was therefore copied into the layer the owner provides:
clearing a local value left it behind, and a binding re-evaluated against
its own result. Read the inherited value instead.
Copilot AI lite review requested due to automatic review settings October 16, 2026 13:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

Clear the stale tooltip container when unregistering it from its owner.

0 open findings

🧠 Review effort: Lite

mikernet added a commit to Singulink/uno that referenced this pull request Oct 16, 2026
…at was subscribed (port)

Port of the latest unoplatform#24592 round (0994593, bd13144, 94e4f41,
d62ceb9 and b825e58 on top of ca34dc1):
- Closing unsubscribes from the elements that were subscribed on open,
  kept in _themeSource and _dataContextSource, instead of reading the
  anchor and the container again, which change when the tooltip is set
  on another element while it is open.
- AttachToPopup and DetachFromPopup carry the inherited DataContext only,
  so a DataContext set or bound on the tooltip itself is not copied into
  the layer the owner provides.
- Popup.Child parents the tooltip: the explicit SetParent calls and the
  guard around the assignment are gone.
- The tests from those commits, the [Bindable] view model they use, and
  the comments.

6.8 differences:
- The theme subscription is still behind UNO_HAS_ENHANCED_LIFECYCLE, and
  the DataContext forwarding has its own unconditional pair (47830b3),
  so _themeSource sits in the gated pair and _dataContextSource in the
  other.
- 6.8 has ReadInheritedValueOrDefaultValue on DependencyObjectStore only,
  so it is called through IDependencyObjectStoreProvider, as Control does.
- Dropping SetParent holds on 6.8 too: Popup.Child goes through the same
  OnChildChangedPartialNative, and PopupPanel.Children.Add and Remove set
  and clear the parent (UIElement.AddChild/RemoveChild on Skia and WASM,
  BindableView on Android).
- The tests live in Tests/Windows_UI_Xaml_Controls. The hover helpers keep
  GetAbsoluteBoundsRect: 7c16adc only fixes the WinAppSDK test build.

unoplatform#25137 (c43992e) carries no source change beyond the earlier port:
ToolTipService.cs already matches it.
@MartinZikmund MartinZikmund closed this pull request by merging all changes into unoplatform:master in 22922a6 Nov 5, 2026
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.

[Skia] ToolTip shows an empty border on first open when its content realizes after load (e.g. ItemsControl) [Regression][Skia] Image inside an open ToolTip stays blank when its source loads after the ToolTip opened

7 participants