Visitar URL original
feat(datacontext)!: Declare DataContext on FrameworkElement only (BC58) by MartinZikmund · Pull Request #23547 · unoplatform/uno · GitHub
Skip to content

feat(datacontext)!: Declare DataContext on FrameworkElement only (BC58) - #23547

Merged
MartinZikmund merged 16 commits into
feature/breakingchangesfrom
dev/mazi/fw-datacontext
Jul 1, 2026
Merged

MartinZikmund merged 16 commits into
feature/breakingchangesfrom
dev/mazi/fw-datacontext

Conversation

@MartinZikmund

Copy link
Copy Markdown
Member

GitHub Issue: closes unoplatform/uno-private#2057 — BC58: DataContext should be declared on FrameworkElement (folds in BC54). Part of the breaking-changes rollup ([[feature/breakingchanges]] base).

PR Type:

💬 Breaking change (feat!) · 🔄 Refactoring

What changed? 🚀

DataContext, DataContextProperty and DataContextChanged are now public members of FrameworkElement only, matching WinUI metadata. They are removed from UIElement and from every non-FrameworkElement DependencyObject (Brush, Transform, Setter, Run, ColumnDefinition/RowDefinition, StateTrigger, VisualState, FlyoutBase, DependencyObjectCollection, ResourceDictionary, ElementFactory, …).

Non-FE objects keep no DataContext of their own, but their {Binding}s still resolve — against the ambient DataContext of the connected FrameworkElement, through the inheritance context (mentor), exactly as WinUI does. Verified against native WinUI that {Binding} resolves on ColumnDefinition.Width, RowDefinition.Height, Run.Text and StateTrigger.IsActive (and not on Setter.Value).

Key pieces:

  • Generator: DependencyObjectGenerator no longer emits a DataContext region/event/partial on non-FE types; DataContext is hand-written on FrameworkElement. The store resolves FrameworkElement.DataContextProperty only when the owner is a FrameworkElement.
  • Inheritance context: a non-FE store routes its inherited DataContext through ApplyDataContext on the parent-inheritance path; an object that opted out of auto-inheritance (e.g. VisualState/VisualStateGroup) registers against its parent once it gains its first child store (fixes late-added StateTrigger binding); a non-FE bindable child attached after its owner already has a DataContext receives it on attach.
  • Flyouts are WinUI-pure: a FlyoutBase has no DataContext. When shown, the placement target's DataContext is forwarded to the presenter (ForwardTargetPropertiesToPresenter) and flyout content/items resolve their bindings through normal visual-tree inheritance — no per-item DataContext push. Removed the MenuFlyout/MenuBarItem pre-show forwarding workarounds.

PR Checklist ✅

Breaking change

DataContext, DataContextProperty and DataContextChanged are no longer available on UIElement or on any non-FrameworkElement DependencyObject.

Migration: cast to FrameworkElement to read/write DataContext on a reference typed as UIElement or a non-FE type (e.g. ((FrameworkElement)element).DataContext). {Binding} on non-FE objects continues to work unchanged. Setting DataContext directly on a standalone non-FE DependencyObject is no longer possible (it was never a WinUI capability).

Validation

  • Unit tests: 0 functional failures (pre-existing Gregorian/DST cases excluded).
  • DependencyObjectGenerator golden tests: 477/477.
  • Skia build: clean.
  • Runtime (Skia Desktop): new Given_NonFE_DataContextBinding parity tests, mentor/multi-parent, subtree, ContextFlyout (show-time), MenuFlyout and attached-flyout binding all pass. Pre-existing flyout-leak/placement runtime tests fail identically on the base branch (GC/window-size environment), unrelated to this change.

🤖 Generated with Claude Code

@github-actions github-actions Bot added area/code-generation Categorizes an issue or PR as relevant to code generation area/build Categorizes an issue or PR as relevant to build infrastructure area/automation Categorizes an issue or PR as relevant to project automation labels Jun 24, 2026
@github-actions

github-actions Bot commented Jun 24, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @MartinZikmund's task in 7m 57s —— View job


PR Review: feat(datacontext)!: Declare DataContext on FrameworkElement only (BC58)

  • Gather context — read key changed files
  • Review core store changes (DependencyObjectStore.cs, DependencyObjectStore.Binder.cs)
  • Review DependencyPropertyDetailsCollection changes
  • Review FrameworkElement.DataContext.cs (new file)
  • Review generator changes (DependencyObjectGenerator.cs)
  • Review flyout/popup changes
  • Review test changes
  • Post inline findings
  • Write summary

Summary

Verdict: Approve with minor fixes. The core architecture is sound and correctly aligned with WinUI parity. The inheritance-context path for non-FE {Binding} resolution — _inheritedDataContext cache in DependencyPropertyDetailsCollection, ApplyDataContext propagation to _childrenStores for non-FE parents, TryRegisterInheritedProperties() on first child-store registration — is a clean solution that handles the mentor/subtree/late-attach scenarios without giving non-FE objects an owned DataContext. The PropagateInheritedValue early return and the ResolveDataContextProperty constructor overload are correctly scoped.

5 findings posted as inline comments (all minor):

Severity File Issue
Minor DependencyObjectStore.cs:214 Duplicate <summary> block left on new single-arg constructor
Minor FrameworkElement.DataContext.cs:1 New file missing #nullable enable (project convention)
Minor DependencyObjectStore.Binder.cs:352 _originalObjectRef ?? ThisWeakReference is dead code (_originalObjectRef is always non-null)
Minor DependencyObjectGenerator.cs:712 Stale comment says "FlyoutBase's internal one" — FlyoutBase no longer declares DataContextProperty
Minor DependencyPropertyDetailsCollection.Bindings.cs:147 FindDataContextBinding() return type should be BindingExpression? to match observable nullability

Cross-cutting notes (not blocking):

  • FlyoutBase.EnsurePopupCreated(object dataContext) — the parameter should be object? since all call sites pass Target?.DataContext (nullable). Not enforced because FlyoutBase.cs lacks #nullable enable, but worth fixing for clarity.
  • DependencyPropertyDetailsCollection.Bindings.cs — the file has no #nullable enable. Adding it would surface the object _inheritedDataContext → object? gap and the FindDataContextBinding return type at compile time rather than relying on callers using is { } pattern defensively.
  • Migration note: the generator no longer emits partial void OnDataContextChangedPartial(DependencyPropertyChangedEventArgs e) on non-FE types. Any consuming code (outside this repo) that overrides this partial on a non-FE DependencyObject will get a compiler error on upgrade. The existing "Migration" section of the PR body covers the DataContext property access path; it may be worth adding a line about OnDataContextChangedPartial for completeness.

@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-23547/wasm-skia-net9/index.html

@github-actions

github-actions Bot commented Jun 24, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @MartinZikmund's task in 4m 58s —— View job


PR Review: feat(datacontext)!: Declare DataContext on FrameworkElement only (BC58)

  • Gather context — read changed files
  • Check if previous 5 findings were addressed
  • Review DependencyObjectStore.cs and .Binder.cs
  • Review FrameworkElement.DataContext.cs and generator changes
  • Review flyout/popup changes (latest commit)
  • Review tests

Summary

Verdict: Approve with minor fixes. The core architecture is sound and the latest commit (fix(flyout): Don't retain owner ViewModel on a shared flyout's popup) is a correct fix. Removing the EnsurePopupCreated(dataContext) parameter, keeping the popup DataContext-free, and forwarding via ForwardTargetPropertiesToPresenter() from Open() cleanly breaks the FlyoutBase → Popup → PlacementTarget → ViewModel retention chain.

Previous 5 findings are still unaddressed (inline comments posted by the previous review run remain open):

Severity File Issue
Minor DependencyObjectStore.cs:205 Duplicate <summary> block on the new single-arg constructor — invalid XML doc
Minor FrameworkElement.DataContext.cs:1 Missing #nullable enable (project convention for new files)
Minor DependencyObjectStore.Binder.cs:352 _originalObjectRef ?? ThisWeakReference is dead code — _originalObjectRef is always non-null
Minor DependencyObjectGenerator.cs:712 Stale comment still says "FlyoutBase's internal one" — FlyoutBase no longer owns DataContextProperty
Minor DependencyPropertyDetailsCollection.Bindings.cs:147 FindDataContextBinding() return type should be BindingExpression?

New cross-cutting notes (not blocking):

  • Double forwarding in ShowAtCore → Open(): ForwardTargetPropertiesToPresenter() is now called twice per normal ShowAtCore invocation — once explicitly in ShowAtCore (line ~550), and again inside Open() (line ~888). The duplication is intentional so that subclasses that override/call Open() directly also get the forwarding. But the ShowAtCore-level call could be removed (relying solely on Open()) for a cleaner single responsibility — the presenter DataContext won't be set any later since Open() forwards before _popup.IsOpen = true. Worth considering for a follow-up.

  • Migration note (PR body): The generator no longer emits partial void OnDataContextChangedPartial(DependencyPropertyChangedEventArgs e) on non-FE types. Downstream code that declared this partial on a non-FE DependencyObject will get a compiler error on upgrade. The existing Migration section covers the property-access path; a line about OnDataContextChangedPartial would round it out.

@github-actions

github-actions Bot commented Jun 24, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @MartinZikmund's task in 6m 2s —— View job


PR Review: feat(datacontext)!: Declare DataContext on FrameworkElement only (BC58)

  • Check if previous 5 findings were addressed — none of the 5 are fixed
  • Review new flyout DataContext leak fix (e1a79ed2)
  • Review new flyout leak tests (4793c357)
  • Review ContentControl.cs, Popup.Base.cs, FlyoutBase.cs changes
  • Re-post inline findings for all 5 outstanding issues
  • Write summary

Summary

Verdict: Still needs the 5 minor fixes from the first review before merge.

The two new commits (e1a79ed2 — fix flyout DataContext leak, 4793c357 — leak test coverage) are correct and well-structured:

  • Removing SynchronizePropertyToPopup(Popup.DataContextProperty, DataContext) from EnsurePopupCreated and deleting OnDataContextChangedPartial eliminates the root cause of the ViewModel retention: the kept-alive shared flyout's popup no longer holds a reference to the owner's DataContext.
  • Adding ForwardTargetPropertiesToPresenter() in ShowAtPosition keeps the show-time forwarding consistent across all ShowAt* paths.
  • ContentControl.cs and Popup.Base.cs guard on DataContextProperty is { } before use — correct null-safety for non-FE stores.
  • The 4 new leak tests in Given_UIElement.ContextFlyoutLeak.cs and the 2 parity tests cover the fixed scenario and WinUI parity.

All 5 findings from the first review remain unaddressed — re-posted as inline comments:

# File Issue
1 DependencyObjectStore.cs:209 Duplicate <summary> block — stale doc from the old two-arg constructor still at lines 205–208
2 FrameworkElement.DataContext.cs:1 New file missing #nullable enable (project convention)
3 DependencyObjectStore.Binder.cs:352 _originalObjectRef ?? ThisWeakReference is dead code (_originalObjectRef always non-null)
4 DependencyObjectGenerator.cs:712 Stale comment says "FlyoutBase's internal one" — FlyoutBase no longer declares DataContextProperty
5 DependencyPropertyDetailsCollection.Bindings.cs:147 FindDataContextBinding() return type should be BindingExpression?

No new issues found in the latest two commits.

@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-23547/wasm-skia-net9/index.html

@nventive-devops

Copy link
Copy Markdown
Contributor

The build 219675 did not find any UI Test snapshots differences.

@unodevops

Copy link
Copy Markdown
Contributor

⚠️⚠️ The build 219675 has failed on Uno.UI - CI.

@MartinZikmund
MartinZikmund force-pushed the dev/mazi/fw-datacontext branch from 4793c35 to d1b529e Compare June 25, 2026 06:51
@github-actions

github-actions Bot commented Jun 25, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @MartinZikmund's task in 3m 59s —— View job


PR Review: feat(datacontext)!: Declare DataContext on FrameworkElement only (BC58)

  • Gather context — check new commits since last review
  • Verify if the 5 previously flagged findings were addressed — none fixed
  • Review new commits (941fd0ee, d1b529ee)
  • Post inline comments for remaining issues
  • Write summary

Summary

Verdict: Still needs the 5 minor fixes before merge. The two new commits are correct and well-motivated.

New commits reviewed

941fd0ee — Clear the non-FE inherited-DataContext cache

  • ClearInheritedDataContext and RestoreInheritedDataContext now properly route through ApplyDataContext(null/dataContext) for non-FE stores — previously these were no-ops for non-FE owners.
  • GetInheritedDataContextValue() correctly reads from _properties.InheritedDataContext (the new cache) for non-FE stores and from the DataContextProperty for FE stores — used correctly in the ALC sweep at DependencyObjectStore.alc.cs:60.
  • InheritedDataContext property correctly exposes the cache for the ALC teardown path.

d1b529ee — Don't push DataContext onto a cross-owner bindable child

  • The parent ownership guard addedProvider.GetParent() is not { } addedParent || ReferenceEquals(addedParent, ActualInstance) correctly mirrors the existing ApplyChildrenBindable guard and prevents a cross-owner push (e.g. presenter setting ItemsSource = flyout.Items would otherwise cache the presenter's DataContext into the flyout's Items collection, which the presenter's close path never clears).
  • New test When_SharedMenuFlyout_Closed_ItemsCollectionReleasesDataContext directly validates the fix deterministically using GetInheritedDataContextValue() without relying on GC.

Still-unaddressed findings (5, all minor, re-posted as inline comments)

# File Issue
1 DependencyObjectStore.cs:205–209 Duplicate <summary> block — stale doc from old two-arg ctor still at lines 205–208
2 FrameworkElement.DataContext.cs:1 New file missing #nullable enable (project convention)
3 DependencyObjectStore.Binder.cs:352 _originalObjectRef ?? ThisWeakReference is dead code (_originalObjectRef always non-null)
4 DependencyObjectGenerator.cs:712 Stale comment says "FlyoutBase's internal one" — FlyoutBase no longer declares DataContextProperty
5 DependencyPropertyDetailsCollection.Bindings.cs:151 FindDataContextBinding() return type should be BindingExpression?

No new issues found in the two latest commits.

@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-23547/wasm-skia-net9/index.html

@nventive-devops

Copy link
Copy Markdown
Contributor

The build 219729 did not find any UI Test snapshots differences.

@nventive-devops

Copy link
Copy Markdown
Contributor

The build 220234 did not find any UI Test snapshots differences.

@unodevops

Copy link
Copy Markdown
Contributor

⚠️⚠️ The build 220234 has failed on Uno.UI - CI.

@MartinZikmund
MartinZikmund enabled auto-merge July 1, 2026 06:20
MartinZikmund and others added 16 commits July 1, 2026 09:54
DataContext, DataContextProperty and DataContextChanged are now public members
of FrameworkElement only, matching WinUI metadata (BC58, uno-private#2057). The
DependencyObjectGenerator no longer emits a DataContext on non-FrameworkElement
DependencyObjects.

Non-FE objects (Brush, ColumnDefinition, Run, StateTrigger, Setter, …) keep no
DataContext of their own but still resolve {Binding}s through the inheritance
context (mentor): the ambient DataContext of the connected FrameworkElement is
applied to their bindings without being stored as a DataContext. Two propagation
gaps the removal exposed are fixed here:
- the parent-inheritance path (OnParentPropertyChangedCallback) routes a non-FE
  store's inherited DataContext through ApplyDataContext;
- an object that opted out of auto-inheritance now registers against its parent
  once it gains its first child store, so a late-added child (e.g. a StateTrigger
  added after its VisualState joined the tree) still receives the DataContext.

A non-FE bindable child attached after its owner already has a DataContext now
receives the current value on attach (previously provided by the per-object
DataContextProperty inheritance).

BREAKING CHANGE: DataContext, DataContextProperty and DataContextChanged are no
longer available on UIElement or any non-FrameworkElement DependencyObject. Cast
to FrameworkElement to access them.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WcF6pCPMSHid3iBj43AxGV
A FlyoutBase is a DependencyObject, not a FrameworkElement, so it has no
DataContext of its own (WinUI parity). Instead of seeding the flyout, popup and
items from the owner's DataContext before showing, the placement target's
DataContext is forwarded to the presenter when the flyout is shown
(ForwardTargetPropertiesToPresenter); flyout content and items then resolve their
{Binding}s through normal visual-tree inheritance from the presenter — exactly as
WinUI does, with no per-item DataContext push.

Removes the Uno-specific MenuFlyout.SetFlyoutItemsDataContext workaround and the
MenuBarItem pre-show forwarding, and excludes FlyoutBase from the mentor so a
flyout never inherits the owner's DataContext before it is shown.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WcF6pCPMSHid3iBj43AxGV
Updates unit and runtime tests for BC58: test doubles that observe DataContext are
FrameworkElements; reads of DataContext on non-FE objects (UIElement, Brush, Run,
MenuFlyout) are replaced with FrameworkElement casts or with binding-based
observation of the inheritance context. Tests that set DataContext directly on a
root non-FE DependencyObject are removed (not a valid scenario under WinUI parity).

Adds Given_NonFE_DataContextBinding (ColumnDefinition/RowDefinition/Run/StateTrigger
{Binding} resolves against the connected FrameworkElement, verified against WinUI),
rewrites the ContextFlyout tests to validate show-time forwarding, and updates the
DependencyObjectGenerator golden (no DataContext region on a non-FE type).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WcF6pCPMSHid3iBj43AxGV
DataContext, DataContextProperty and DataContextChanged were removed from
UIElement and every non-FrameworkElement DependencyObject (BC58). Add the
corresponding entries to PackageDiffIgnore so the API-diff check accepts the
intentional removals.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WcF6pCPMSHid3iBj43AxGV
EnsurePopupCreated forwarded the placement target's DataContext onto the flyout's
Popup, which is kept alive by a shared flyout (e.g. TextCommandBarFlyout) and was
never cleared once the OnDataContextChangedPartial path was removed. After close,
the presenter's DataContext was cleared back to that popup value and re-propagated
to the (kept-alive) MenuFlyout items, leaking the owner's ViewModel.

The popup now carries no DataContext: the target's DataContext is forwarded to the
presenter at show-time (ForwardTargetPropertiesToPresenter, now also from Open) and
cleared on close, so closing the flyout releases the owner's ViewModel.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WcF6pCPMSHid3iBj43AxGV
…ntext

Deterministic (GC-independent) regression for the shared-flyout ViewModel leak:
asserts a MenuFlyout item inherits the owner's DataContext while open and no longer
carries it after the flyout closes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WcF6pCPMSHid3iBj43AxGV
ClearInheritedDataContext / RestoreInheritedDataContext were no-ops for a
non-FrameworkElement store (they only acted through the now-removed
DataContextProperty), so a non-FE object's cached mentor DataContext was never
released. Route them through ApplyDataContext for non-FE stores, and adapt the
new ALC-teardown sweep (DependencyObjectStore.alc.cs) to read the inherited value
from that cache when the owner has no DataContextProperty (BC58).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WcF6pCPMSHid3iBj43AxGV
…child

The on-attach DataContext push pushed the owner's DataContext onto any newly-added
non-FE bindable child, without the ownership guard ApplyChildrenBindable uses. A
MenuFlyout's Items collection is parented to the flyout but set as the presenter's
ItemsSource, so on show the presenter pushed its DataContext (the owner ViewModel)
into the collection's inheritance-context cache — and the presenter's clear on close
skips it (its parent is the flyout, not the presenter), so it was never released.
A shared flyout keeps that collection alive, leaking the owner's ViewModel
(When_SharedContextFlyout_DoesNotLeak_ViewModel).

Apply the same parent guard as ApplyChildrenBindable: only push onto a child whose
parent is null or this owner. Validated deterministically by
When_SharedMenuFlyout_Closed_ItemsCollectionReleasesDataContext.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WcF6pCPMSHid3iBj43AxGV
A FlyoutBase is a non-FrameworkElement, so it has no DataContextProperty
for the inheritance system to reset when its owner leaves the tree. On
EnterImpl the owner's DataContext is cached in the flyout's inheritance
context; on detach that cache was never cleared, so a shared flyout kept
alive (e.g. TextCommandBarFlyout) pinned the last owner's ViewModel.

Mirror FrameworkElement detach semantics: clear a non-FE store's inherited
DataContext when its parent is removed. Adds a GC-independent deterministic
guard (reliable on the headless runner unlike the WeakReference leak tests).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- FrameworkElement.DataContext.cs: enable #nullable, mark DataContext object?
  and the DataContextChanged event nullable.
- DependencyObjectStore.Binder.cs: drop redundant ThisWeakReference fallback.
- DependencyPropertyDetailsCollection.Bindings.cs: annotate FindDataContextBinding
  nullable.
- DependencyObjectGenerator.cs: correct hand-written-DataContext comment.
- Given_ItemsRepeater.cs: null-forgive DataContext now that it is object?.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The shared-flyout ViewModel leak had a second, deeper cause. A flyout
presenter's templated brushes come from merged/theme ResourceDictionaries
that stay alive for the app's lifetime. When the presenter is shown with the
owner's DataContext, those resources received it through the bindable-child
path (ApplyChildrenBindable / on-attach push -> SetInheritedDataContext) and
cached it in their non-FE _inheritedDataContext. The existing resource guard
only covered the parent-inheritance path, so the resource kept the ViewModel
alive forever.

Block DataContext caching for ResourceDictionary items at the ApplyDataContext
chokepoint, matching the OnParentPropertyChangedCallback guard (WinUI:
resources have no DataContext). Found via a multi-root reflection graph-walk;
guarded by a GC-independent deterministic test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per review feedback, remove the cryptic `BC58` citations from code
comments and PackageDiffIgnore reasons, and drop the private
`uno-private#2057` reference from repo-tracked files. Reword the two
removal-narration comments to describe present intent instead.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KR38MQrgHDxMfwp9fEBkdt
Parametrize When_StateTrigger_IsActive_Bound with true/false DataRows
so the bound StateTrigger is asserted in both directions, and remove the
trailing no-op root.Children.Clear() calls at the end of the show-time
forwarding flyout tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KR38MQrgHDxMfwp9fEBkdt
Wrap the ResetContentDataContextOverride guard across lines per the
review suggestion, and import System.Diagnostics.CodeAnalysis and
Windows.Foundation in FrameworkElement.DataContext.cs to drop the
global:: qualifiers.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KR38MQrgHDxMfwp9fEBkdt
FlyoutBase no longer hand-declares an internal DataContext; the only
type that hand-writes DataContextProperty is FrameworkElement.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A non-FE child carrying a pre-existing {Binding} that joins a collection
after the owner already has a DataContext must resolve via the on-attach
push, replacing the removed DependencyObjectCollection coverage.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@MartinZikmund
MartinZikmund force-pushed the dev/mazi/fw-datacontext branch from 13cb352 to 6b57897 Compare July 1, 2026 07:54
@github-actions

github-actions Bot commented Jul 1, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @MartinZikmund's task in 1m 48s —— View job


PR Review: feat(datacontext)!: Declare DataContext on FrameworkElement only (BC58)

  • Gather context — identify new commits since last review (2026-06-30)
  • Review new commits (8ffdecdb, 6b57897c)
  • Check that previous findings remain resolved — all 5 still fixed
  • Check for new issues — none found
  • Write summary

Summary

Verdict: ✅ Approve. The two new commits are clean, targeted, and correct. No new issues found, and all 5 previously flagged findings remain resolved.

New commits reviewed

8ffdecdb — docs(datacontext): Fix stale FlyoutBase DataContext note
Removes the stale "and kept internal on FlyoutBase" phrase from the DependencyObjectGenerator.cs comment (directly addresses Martin's "Kept internal?" question). The comment now reads:

DataContext is a FrameworkElement-only property (WinUI parity): it is hand-written on FrameworkElement and the generator no longer emits it on every DependencyObject.
This is accurate — FlyoutBase has no DataContext at all; FrameworkElement is the sole type that hand-declares it.

6b57897c — test(datacontext): Cover on-attach DataContext push
Adds When_Grid_NonFE_Child_PreBound_Added_After_DataContext to Given_DependencyProperty.ManualPropagation.cs. This directly fills the coverage gap flagged in the previous review ("binding-added-after-DataContext-already-on-parent-FE" scenario unverified). The test:

  • Sets DataContext on the Grid first
  • Adds a {Binding} to a standalone ColumnDefinition (precondition asserts it hasn't resolved: GridUnitType.Star)
  • Adds the column to the grid — the on-attach push delivers the ambient DataContext
  • Asserts the binding resolved (GridUnitType.Pixel, value 42)

Pattern is consistent with the existing When_Grid_DataBound_Setters test (same string-typed DataContext, same assertion style).

Previously flagged findings — all still resolved

# File Status
1 DependencyObjectStore.cs — duplicate <summary> block ✅ Fixed in bdc2cf3d
2 FrameworkElement.DataContext.cs — missing #nullable enable ✅ Fixed in 5a5cd88b
3 DependencyObjectStore.Binder.cs — dead ?? ThisWeakReference ✅ Fixed in 5a5cd88b
4 DependencyObjectGenerator.cs — stale FlyoutBase comment ✅ Fixed in 8ffdecdb
5 DependencyPropertyDetailsCollection.Bindings.cs — FindDataContextBinding() return type ✅ Fixed in 5a5cd88b

@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-23547/wasm-skia-net9/index.html

@nventive-devops

Copy link
Copy Markdown
Contributor

The build 220375 did not find any UI Test snapshots differences.

@MartinZikmund
MartinZikmund merged commit cf6ca19 into feature/breakingchanges Jul 1, 2026
66 checks passed
@MartinZikmund
MartinZikmund deleted the dev/mazi/fw-datacontext branch July 1, 2026 10:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/automation Categorizes an issue or PR as relevant to project automation area/build Categorizes an issue or PR as relevant to build infrastructure area/code-generation Categorizes an issue or PR as relevant to code generation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants