microsoft / microsoft-ui-xaml

Windows UI Library: the latest Windows 10 native controls and Fluent styles for your applications
MIT License
6.35k stars 678 forks source link

ResourceManagerRequested event is not working in Islands sample (sample bug) #8971

Open Ajith-GS opened 1 year ago

Ajith-GS commented 1 year ago

Describe the bug

I have downloaded the XAML hosting sample application available in the WindowsAppSDK-Samples repo. It's working fine. My problem is that the ResourceManagerRequested event is not hitting. I am trying to implement a custom resource manager using the CustomResourceManager property available in the ResourceManagerRequestedEventArgs. But it never entering into the event handler. Are we not able to use the ResourceManagerRequested event in WinUI3 XAML Island applications? Is there anything I am missing to trigger the ResourceManagerRequested event in an XAML-hosted application? Is there any workaround available to implement the custom resource manager?

Any help is much appreciated

Steps to reproduce the bug

  1. Download and build the XAML Island sample application available in the following branch. https://github.com/microsoft/WindowsAppSDK-Samples/tree/main/Samples/Islands

  2. Add the following header and namespaces in pch.h file.

    #include <winrt\Microsoft.Windows.ApplicationModel.Resources.h>
    namespace winrt
    {
    using namespace Windows::Foundation;
    using namespace winrt::Microsoft::Windows::ApplicationModel::Resources;
    }
  3. Add the following line of code inside the constructor of the App class available in the "App.xaml.h" file.

    this->ResourceManagerRequested([this](winrt::IInspectable const&, winrt::ResourceManagerRequestedEventArgs const& EventArgs)
    {
    OutputDebugString(L"\nResourceManagerRequested...\n");
    });
  4. Build and run the application.

Expected behavior

The ResourceManagerRequested event should be called and OutputDebugString content should be shown during startup .

Screenshots

The ResourceManagerRequested event is never called.

NuGet package version

Windows App SDK 1.4.2: 1.4.231008000

Packaging type

Unpackaged

Windows version

Windows 10 version 22H2 (19045, 2022 Update)

IDE

Visual Studio 2022

Additional context

I have tried the following way, too. But there was no effect. Add the following code with the necessary headers and namespaces after the auto simpleIslandApp{ winrt::make<winrt::SimpleIslandApp::implementation::App>() }; line available in the SimpleIslandApp.cpp file :

simpleIslandApp.ResourceManagerRequested([](winrt::IInspectable const&, winrt::ResourceManagerRequestedEventArgs const& EventArgs) { OutputDebugString(L"\nResourceManagerRequested...\n"); });

evelynwu-msft commented 1 year ago

This is the result of a race condition in the sample. Specifically, the call to winrt::Microsoft::UI::Xaml::Hosting::WindowsXamlManager::InitializeForCurrentThread() causes the XAML core to be initialized and so the Application.ResourceManagerRequested event is raised by the framework before the app gets a chance to register its event handler. If you instead rewrite the constructor to look like the below snippet then the event handler is invoked as expected.

        App()
        {
            this->ResourceManagerRequested([this](winrt::IInspectable const&, winrt::Microsoft::UI::Xaml::ResourceManagerRequestedEventArgs const& /*unused*/)
            {
                OutputDebugString(L"\nResourceManagerRequested...\n");
            });
            m_windowsXamlManager = winrt::Microsoft::UI::Xaml::Hosting::WindowsXamlManager::InitializeForCurrentThread();
        }

I'm going to leave this issue open because we should be able to improve this experience somehow, whether by augmenting the API or even just documenting it more clearly, but the above is hopefully sufficient to unblock you.

Ajith-GS commented 1 year ago

This is the result of a race condition in the sample. Specifically, the call to winrt::Microsoft::UI::Xaml::Hosting::WindowsXamlManager::InitializeForCurrentThread() causes the XAML core to be initialized and so the Application.ResourceManagerRequested event is raised by the framework before the app gets a chance to register its event handler. If you instead rewrite the constructor to look like the below snippet then the event handler is invoked as expected.

        App()
        {
            this->ResourceManagerRequested([this](winrt::IInspectable const&, winrt::Microsoft::UI::Xaml::ResourceManagerRequestedEventArgs const& /*unused*/)
            {
                OutputDebugString(L"\nResourceManagerRequested...\n");
            });
            m_windowsXamlManager = winrt::Microsoft::UI::Xaml::Hosting::WindowsXamlManager::InitializeForCurrentThread();
        }

I'm going to leave this issue open because we should be able to improve this experience somehow, whether by augmenting the API or even just documenting it more clearly, but the above is hopefully sufficient to unblock you.

The workaround described above works for me. Thank you very much for your help.