Search code examples
c++windows-runtimec++-cxwrl

How to activate an instance of a ref class


Say I have this class:

public ref class Page1 sealed : Windows::UI::Xaml::Controls::Page {};

I can activate an instance of this class like this:

auto page = ref new Page1();

But how would I do that in raw C++?

I have tried this but it doesn't work:

Microsoft::WRL::Wrappers::HString className;
className.Set(L"App1.Page1");
IInspectable *page;
Windows::Foundation::ActivateInstance(className.Get(), &page);

The above code does work when I specify a windows runtime class name, (such as "Windows.UI.Xaml.Controls.Button"), just not my own ref class "App1.Page1".


Alternatively, given that I have declared a public ref class named Page1 in the App1 namespace, how can I activate an instance of this class as an IInspectable* from the HSTRING "App1.Page1"?


Solution

  • I think I have figured it out. Well, this answer does not directly solve the problem of activating any arbitrary type, but it does what I want.

    The devil is in the detail. The XAML compiler will generate a bunch of files not visible in the Solution Explorer. These files have the extension .g.h and .g.hpp. You can click the "Show All Files" button in Solution Explorer to see them.

    In App.g.h, the App class implements the Windows::UI::Xaml::Markup::IXamlMetadataProvider class, which we can use to obtain information about our XAML types. The XamlTypeInfo files contains the generated type definitions.

    Here's some code which shows how to activate one of our XAML types from a TypeName:

    Object^ activate(TypeName typeName)
    {
        auto app = Application::Current;
        auto provider = static_cast<IXamlMetadataProvider^>(app);
        auto xamlType = provider->GetXamlType(typeName);
        return xamlType->ActivateInstance();
    }
    

    No WRL necessary, 100% C++/CX, thanks to the XAML type information generated by the XAML compiler!

    I believe a similar structure is also the case for C# projects, in that the Application-derived class will implement IXamlMetadataProvider interface too. Under the hood, the Windows Runtime does not use .NET, so it does not have any kind of "real" reflection, so it relies on statically defined type definitions.