Skip to content

Conversation

@anupriya13
Copy link

@anupriya13 anupriya13 commented Dec 16, 2025

Overview

This PR upgrades the Windows implementation of the Picker component to use the new architecture based on XAML Islands. The goal is to modernize the component, improve compatibility with recent React Native Windows changes, and ensure better long-term support.

Design and Implementation

XAML Islands Integration

  • The Windows Picker now leverages XAML Islands, enabling seamless integration of modern XAML controls within React Native Windows apps.
  • This approach decouples the UI rendering from older Win32 components, allowing richer user interfaces and smoother theming.

Architecture Changes

  • The refactored Picker internally communicates with native modules using updated bridges compatible with the latest React Native Windows architecture.
  • State synchronization between JavaScript and native code has been streamlined for improved reliability and performance.
  • Legacy code and obsolete workarounds tied to the previous implementation have been removed to reduce technical debt.

Spec File Changes

  • All the code in “js” directory are for ios and android which remain untouched and as it is while all the code in “src” directory are for windows.
    I have removed the old implementation of windows in “js” directory for Picker.

Testing Instructions

  1. Build the Windows solution in both Debug and Release modes.
  2. Run the sample app and verify that Picker behaves as expected:
    • Options render correctly
    • User can select items
    • No regressions in input methods (keyboard, mouse, touch)

Note

  • It has Windows changes only!
  • Needs react-native 0.82+ and react-native-windows 0.82+ versions. As RNW 0.82 is not released yet, I have used canary version of RNW. Feel free to block this PR till RNW 0.82 is released for stable build.

Screenshots and videos

image image image
picker_3p_windows.mp4

@anupriya13 anupriya13 marked this pull request as ready for review December 17, 2025 06:39
@anupriya13
Copy link
Author

@Naturalclar Please review - windows new arch picker implementation

Comment on lines 73 to 75
if (m_updating) {
return;
}

Choose a reason for hiding this comment

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

Why is m_updating needed? I mean, when control is in UpdateProps can this code path be hit? That shouldn't be a possibility in a single-threaded app. Do the event handlers get called in a different thread?

Copy link
Author

@anupriya13 anupriya13 Dec 24, 2025

Choose a reason for hiding this comment

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

Great question! You're right that this is a single-threaded app, but m_updating is still needed for a different reason.

When we programmatically set properties like SelectedIndex, Items, etc. in UpdateProps these calls synchronously trigger the event handlers on the same thread. So m_updating distinguishes between:

Programmatic changes (syncing props from JS -> native): We should not emit events back to JS
User interactions (clicking dropdown): We should emit events to JS

Let me know your thoughts...

Choose a reason for hiding this comment

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

A better option would be to temporarily detach and attach handler as it's localized i.e. the change, and its repercussions are visible in the same place. OTOH a member variable is globalized i.e. a state that is visible across functions and confuse people (like I got and asked a question around it). Generally state variables are error-prone, needs consistent updating and fiddly.

    // Revoke (detach) - just reset the revoker
    m_sliderValueChangedRevoker. revoke();
    
    // Set the value without triggering the handler
    MySlider().Value(newValue);
    
    // Re-register the event handler
    m_sliderValueChangedRevoker = MySlider().ValueChanged(
        winrt::auto_revoke,
        { this, &MyPage:: OnSliderValueChanged });

You can use RAII to never forget to attach the handler back:

// Runs code with auto detach and attach of event handler.
static
template<typename TRevoker, typename TSetup, typename TAction>
void WithEventSuspended(TRevoker& revoker, TSetup setup, TAction action)
{
    revoker.revoke();
    action();
    revoker = setup();
}

// Usage:
void MyPage::UpdateSliderProgrammatically(double newValue)
{
    WithEventSuspended(
        m_sliderValueChangedRevoker,
        [this]() { 
            return MySlider().ValueChanged(
                winrt::auto_revoke, 
                { this, &MyPage::OnSliderValueChanged }); 
        },
        [this, newValue]() { 
            MySlider().Value(newValue); 
        });
}

I've shown a slider value changed example for simplicity. You can adapt it to your needs.

Copy link

@sundaramramaswamy sundaramramaswamy Dec 31, 2025

Choose a reason for hiding this comment

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

I see this is resolved but not changes were made nor a comment was left. I'm confused. Do you agree and forgot to make changes? You disagree and forgot to give reasons?

Copy link
Author

Choose a reason for hiding this comment

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

This was resolved on my first comment and never unresolved on your second comment. I have unresolved now and will work on the fix you suggested.

Copy link

@sundaramramaswamy sundaramramaswamy left a comment

Choose a reason for hiding this comment

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

Signing off with some comments. Please address them. LGTM otherwise!

Comment on lines 73 to 75
if (m_updating) {
return;
}

Choose a reason for hiding this comment

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

A better option would be to temporarily detach and attach handler as it's localized i.e. the change, and its repercussions are visible in the same place. OTOH a member variable is globalized i.e. a state that is visible across functions and confuse people (like I got and asked a question around it). Generally state variables are error-prone, needs consistent updating and fiddly.

    // Revoke (detach) - just reset the revoker
    m_sliderValueChangedRevoker. revoke();
    
    // Set the value without triggering the handler
    MySlider().Value(newValue);
    
    // Re-register the event handler
    m_sliderValueChangedRevoker = MySlider().ValueChanged(
        winrt::auto_revoke,
        { this, &MyPage:: OnSliderValueChanged });

You can use RAII to never forget to attach the handler back:

// Runs code with auto detach and attach of event handler.
static
template<typename TRevoker, typename TSetup, typename TAction>
void WithEventSuspended(TRevoker& revoker, TSetup setup, TAction action)
{
    revoker.revoke();
    action();
    revoker = setup();
}

// Usage:
void MyPage::UpdateSliderProgrammatically(double newValue)
{
    WithEventSuspended(
        m_sliderValueChangedRevoker,
        [this]() { 
            return MySlider().ValueChanged(
                winrt::auto_revoke, 
                { this, &MyPage::OnSliderValueChanged }); 
        },
        [this, newValue]() { 
            MySlider().Value(newValue); 
        });
}

I've shown a slider value changed example for simplicity. You can adapt it to your needs.

Copy link

@sundaramramaswamy sundaramramaswamy left a comment

Choose a reason for hiding this comment

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

Please reply to comments.

@gmacmaster
Copy link

Is there a rough estimate for when RNW 0.82 will be released?

@anupriya13 anupriya13 changed the title Picker - Upgrade Windows to New Arch using XAML Islands [Do not merge till RNW 0.82 is released] Picker - Upgrade Windows to New Arch using XAML Islands Jan 2, 2026
@anupriya13
Copy link
Author

Is there a rough estimate for when RNW 0.82 will be released?

Yes around Feb'26 or end of Jan'26

anupriya13 and others added 4 commits January 2, 2026 10:59
Co-authored-by: Sundaram Ramaswamy <suramaswamy@microsoft.com>
Co-authored-by: Sundaram Ramaswamy <suramaswamy@microsoft.com>
@anupriya13
Copy link
Author

All comments are resolved. Now only waiting for RNW 0.82 Stable version to be released to merge this PR.

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.

3 participants