Search code examples
c++-winrt

Is it possible to programatically create a xaml page?


I might write no sense on the next lines:

I tried to derive a struct named mainpage from winrt::Windows::UI::Xaml::Controls::Page and pass it to winrt::xaml_typename<>(), in "<>" is mainpage.

It will be understandable when you look at the code: Point number 1 "(1)" is the mainpage.h file, is very short. Point number 2 "(2)" is the App.cpp file, it only has the necessary.

//(1) mainpage.h

#pragma once

#include "pch.h"

struct mainpage : winrt::Windows::UI::Xaml::Controls::Page
{
    mainpage() {

        winrt::Windows::UI::Xaml::Controls::Button thebutton = winrt::Windows::UI::Xaml::Controls::Button();
        thebutton.Click([&](const IInspectable& sender, const winrt::Windows::UI::Xaml::RoutedEventArgs& event_arg)
        {
            thebutton.Content(winrt::box_value(L"Clicked"));
        });
    }
};

//(2) App.cpp

#include "pch.h"
#include "mainpage.h"

struct App : winrt::Windows::UI::Xaml::ApplicationT<App>
{
    void OnLaunched(const winrt::Windows::ApplicationModel::Activation::LaunchActivatedEventArgs& event_arg)
    {
        winrt::Windows::UI::Xaml::Controls::Frame root_frame{ nullptr };
        winrt::Windows::UI::Xaml::UIElement content = winrt::Windows::UI::Xaml::Window::Current().Content();
        if (content)
        {
            root_frame = content.try_as<winrt::Windows::UI::Xaml::Controls::Frame>();
        }

        // Do not repeat app initialization when the Window already has content,
        // just ensure that the window is active
        if (root_frame == nullptr)
        {
            // Create a Frame to act as the navigation context and associate it with
            // a SuspensionManager key
            root_frame = winrt::Windows::UI::Xaml::Controls::Frame();

            root_frame.NavigationFailed({ this, &App::OnNavigationFailed });

            if (event_arg.PreviousExecutionState() == winrt::Windows::ApplicationModel::Activation::ApplicationExecutionState::Terminated)
            {
                // Restore the saved session state only when appropriate, scheduling the
                // final launch steps after the restore is complete
            }

            if (event_arg.PrelaunchActivated() == false)
            {
                if (root_frame.Content() == nullptr)
                {
                    // When the navigation stack isn't restored navigate to the first page,
                    // configuring the new page by passing required information as a navigation
                    // parameter
                    root_frame.Navigate(winrt::xaml_typename<mainpage>(), box_value(event_arg.Arguments()));
                }
                // Place the frame in the current Window
                winrt::Windows::UI::Xaml::Window::Current().Content(root_frame);
                // Ensure the current window is active
                winrt::Windows::UI::Xaml::Window::Current().Activate();
            }
        }
        else
        {
            if (event_arg.PrelaunchActivated() == false)
            {
                if (root_frame.Content() == nullptr)
                {
                    // When the navigation stack isn't restored navigate to the first page,
                    // configuring the new page by passing required information as a navigation
                    // parameter
                    root_frame.Navigate(winrt::xaml_typename<mainpage>(), box_value(event_arg.Arguments()));
                }
                // Ensure the current window is active
                winrt::Windows::UI::Xaml::Window::Current().Activate();
            }
        }
    }
    void App::OnNavigationFailed(const IInspectable&, const winrt::Windows::UI::Xaml::Navigation::NavigationFailedEventArgs& event_arg)
    {
        throw winrt::hresult_error(E_FAIL, winrt::hstring(L"Failed to load Page ") + event_arg.SourcePageType().Name);
    }
};

int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int) {
    winrt::Windows::UI::Xaml::Application::Start([](auto &&) { winrt::make<App>(); });
}

If it is not possible, how can I properly create a page?


Solution

  • It is simple if you have installed the CppWinRT VSIX. Then create a "View model" and edit the files. You shouldn't derive the struct from the winrt::Windows::UI::Xaml::Controls::Page class because winrt::xaml_typename<> needs a WinRT class in <>.