How can I share a view model between different pages in a C++ UWP application?
This answer is a C# solution which uses a static property:
public sealed partial class MainPage : Page
{
public AppViewModel ViewModel { get; set; } = new AppViewModel();
public static MainPage Current { get; set; }
public MainPage()
{
this.InitializeComponent();
Current = this;
}
}
But I am having trouble translating that into C++.
My C++ MainPage
currently looks like this:
namespace winrt::myproject::implementation
{
struct MainPage : MainPageT<MainPage>
{
MainPage();
myproject::MainViewModel MainViewModel() const { return this->mainViewModel; }
private:
myproject::MainViewModel mainViewModel{ nullptr };
};
}
The view model instance is created in the MainPage()
constructor using
this->mainViewModel = winrt::make<myproject::implementation::MainViewModel>();
And the .idl
file simply lists the view model instance as a property:
[default_interface]
runtimeclass MainPage : Windows.UI.Xaml.Controls.Page
{
MainPage();
MainViewModel MainViewModel{ get; };
}
How can I share the MainViewModel
between all of my pages?
What do I need to change in the .idl
and in the .h
file?
Do I need to use std::shared_ptr<myproject::MainViewModel>
or winrt::comptr<myproject::MainViewModel>
to avoid copying the struct and to really share the same instance?
myproject::MainViewModel
ultimately derives from winrt::Windows::Foundation::IUnknown
. It is this structure that implements all the reference counting machinery, turning each derived type into a shared pointer to its interface.
The following implementation
myproject::MainViewModel MainViewModel() const { return this->mainViewModel; }
invokes the IUnknown::IUnknown(IUnknown const& other)
copy-c'tor that increments the reference count on other
and constructs an IUnknown
instance holding the same pointer. Both this->mainViewModel
and the return value point to the same object.
In general, copying structures that represent projected types performs a shallow copy. Only the pointer to the object is copied, and the reference count is incremented. Like a std::shared_ptr
the operation is thread-safe and has comparable overhead.
A lot more information on the internals and use of projected types can be found at Consume APIs with C++/WinRT.