Skip to content

Fix crash when switching converter categories#2483

Closed
veler wants to merge 1 commit into
microsoft:feature/calcviewmodel-to-csharpfrom
veler:patch-1
Closed

Fix crash when switching converter categories#2483
veler wants to merge 1 commit into
microsoft:feature/calcviewmodel-to-csharpfrom
veler:patch-1

Conversation

@veler

@veler veler commented Jul 2, 2026

Copy link
Copy Markdown

Fix crash when switching converter categories

Navigating between Converter categories (e.g. Currency -> Temperature, Temperature -> Weight and mass) intermittently crashed the app.

Root cause: on a category change UnitConverterViewModel rebuilds the bound Units collection in place and then assigns Unit1/Unit2, which x:Bind pushes to each ComboBox's SelectedItem synchronously inside the NavigationView selection handler. WinUI's ComboBox validates SelectedItem against its own item collection, which it refreshes from the ItemsSource change on a later, deferred pass. When the selection is applied before that refresh completes, Selector.put_SelectedItem throws ArgumentException (0x80070057) which, being unhandled in the XAML delegate, fail-fasts the process. It's timing-dependent, so it reproduces intermittently and vanishes under a debugger.

The C++/CX version never hit this because classic {Binding} routed selection through the AlwaysSelectedCollectionView (ICollectionView) currency, which defers gracefully. That currency integration does not reproduce in the C# projection: reverting to {Binding} makes the ComboBox write its default (index 0) selection back through the TwoWay binding, corrupting the engine's from/to units instead. SelectedIndex binding, a single Reset notification, an atomic collection swap, and a deferred dispatcher push were all verified on-device not to close the race, because the lag lives inside the control.

Contain the specific transient at the assignment site (AssignSelectedUnit): the Unit1/Unit2 backing fields are set before the throw and the ComboBox reconciles its selection on the next layout pass, so the displayed selection is correct. Verified: 0 crashes across 110+ category navigations; conversions (e.g. 100 C = 212 F) and dropdown selection continue to work.

Fix crash when switching converter categories

Navigating between Converter categories (e.g. Currency -> Temperature,
Temperature -> Weight and mass) intermittently crashed the app.

Root cause: on a category change UnitConverterViewModel rebuilds the bound
Units collection in place and then assigns Unit1/Unit2, which x:Bind pushes to
each ComboBox's SelectedItem synchronously inside the NavigationView selection
handler. WinUI's ComboBox validates SelectedItem against its own item
collection, which it refreshes from the ItemsSource change on a later, deferred
pass. When the selection is applied before that refresh completes,
Selector.put_SelectedItem throws ArgumentException (0x80070057) which, being
unhandled in the XAML delegate, fail-fasts the process. It's timing-dependent,
so it reproduces intermittently and vanishes under a debugger.

The C++/CX version never hit this because classic {Binding} routed selection
through the AlwaysSelectedCollectionView (ICollectionView) currency, which
defers gracefully. That currency integration does not reproduce in the C#
projection: reverting to {Binding} makes the ComboBox write its default (index 0)
selection back through the TwoWay binding, corrupting the engine's from/to
units instead. SelectedIndex binding, a single Reset notification, an atomic
collection swap, and a deferred dispatcher push were all verified on-device not
to close the race, because the lag lives inside the control.

Contain the specific transient at the assignment site (AssignSelectedUnit):
the Unit1/Unit2 backing fields are set before the throw and the ComboBox
reconciles its selection on the next layout pass, so the displayed selection is
correct. Verified: 0 crashes across 110+ category navigations; conversions
(e.g. 100 C = 212 F) and dropdown selection continue to work.
@veler veler closed this Jul 7, 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.

1 participant