Unpackaged 0.0.7
See the version list below for details.
dotnet add package Unpackaged --version 0.0.7
NuGet\Install-Package Unpackaged -Version 0.0.7
<PackageReference Include="Unpackaged" Version="0.0.7" />
paket add Unpackaged --version 0.0.7
#r "nuget: Unpackaged, 0.0.7"
// Install Unpackaged as a Cake Addin #addin nuget:?package=Unpackaged&version=0.0.7 // Install Unpackaged as a Cake Tool #tool nuget:?package=Unpackaged&version=0.0.7
CppXAML
CppXAML aims to make usage of XAML and XAML islands in C++ more natural and idiomatic.
C++/WinRT provides a projection of a Windws Runtime component's API, but one that isn’t always easy to use (esp. for XAML). It also is unopinionated w.r.t. how to implement properties. This added flexibility can be good, but is often unnecessary and results in overly-verbose code.
CppXAML provides several kinds of higher-level helpers. Usage information can be found below. See also API reference.
XamlWindow
XAMLWindow implements an HWND based host for XAML Islands. You can create a XamlWindow
from one of three overloads of Make:
- Host a build-time XAML
UIElement
(usually defined in a runtime component project, often will be aPage
) API:
Usage:template<typename TUIElement> static XamlWindow& Make(PCWSTR id, AppController* controller = nullptr);
auto& mainWindow = cppxaml::XamlWindow::Make<MarkupSample::MainPage>(L"MarkupSample", &controller);
- Host UI created from markup at runtime:
API:
Usage:static XamlWindow& Make(PCWSTR id, std::wstring_view markup, AppController* c = nullptr)
auto& xw = cppxaml::XamlWindow::Make(L"MyPage", LR"( <StackPanel> <TextBlock>Hello</TextBlock> </StackPanel>)", &controller);
- Host UI created programmatically at runtime:
API:
Usage:static XamlWindow& Make(PCWSTR id, winrt::Windows::UI::Xaml::UIElement(*getUI)(const XamlWindow&), AppController* c = nullptr);
auto& xw = cppxaml::XamlWindow::Make(L"Foo", [](auto&...) { return winrt::Windows::UI::Xaml::Controls::Button(); });
Parenting flyouts
To parent a flyout or context menu, you may use one of the InitializeWithWindow
methods:
- Initialize with a WinUI 3
Window
-like object:template<typename TWindow> std::enable_if_t<!std::is_assignable_v<TWindow, cppxaml::XamlWindow*>> InitializeWithWindow(winrt::Windows::Foundation::IInspectable obj, TWindow /*winrt::Microsoft::UI::Xaml::Window*/ w)
- Initialize with an
HWND
:bool InitializeWithWindow(cppxaml::xaml::FrameworkElement obj, HWND hwnd)
- Initialize with a
XamlWindow
:void InitializeWithWindow(cppxaml::xaml::FrameworkElement obj, const cppxaml::XamlWindow* xw)
AppController
AppController
is responsible for coordinating XamlWindow instances, can extend their wndproc, and provides an opportunity to hook up event handlers once a XAML UI becomes live
Property and event helpers
XamlProperty<T>
SimpleNotifyPropertyChanged<F>
XamlPropertyWithNPC<T>
XamlEvent<T>
XamlTypedEvent<TSender, TArgs>
These provide stock/simple property objects that remove the need for verbose hand-written options.
Examples:
MainPage.h:
cppxaml::XamlEvent<winrt::hstring> OkClicked;
cppxaml::XamlProperty<winrt::hstring> InterfaceStr;
cppxaml::XamlProperty<winrt::hstring> InterfaceStrWithNPC;
MainPage.cpp:
MainPage::MainPage() : INIT_PROPERTY(MyInt, 42)
{
InitializeComponent();
// Properties can be assigned to and read from with the operator= too!
ImplString = winrt::hstring{ L"This string comes from the implementation" };
winrt::hstring v = ImplString;
}
Control helpers
CppXAML includes some primitives to make it more natural to write XAML UI in code.
TextBlock
Most commonly, you will want to construct a TextBlock
from a string of text. This can be a bit cumbersome if you are using C++/WinRT directly. With cppxaml, you can just write:
auto tb = cppxaml::TextBlock(L"Hello");
xaml
Namespace alias
Since we want CppXAML to be future proof and work with WinUI 3, CppXAML creates a namespace alias cppxaml::xaml
which points at either Windows::UI::Xaml
or Microsoft::UI::Xaml
for system XAML or WinUI 3, respectively.
Fluent-style programming style
C++/WinRT enables setting properties on a type by calling a property setter method, e.g. myTextBlock.Text(L"text");
. If you then want to set another property, then you have to make another call myTextBlock.XYZ(...);
. This can get verbose when having to set multiple properties. CppXAML enables writing fluent-style code instead of the former imperative-style:
auto myTextBlock = cppxaml::TextBlock(L"Hello world")
.Margin(4)
.Padding(6)
.Name(L"myTB");
StackPanel
Panels in XAML can have zero or more children. CppXAML makes it easy to naturally describe a panel's children with an initializer list. For example:
auto sp = cppxaml::StackPanel({
cppxaml::TextBlock(L"Hello"),
cppxaml::TextBlock(L"world!")
});
You can also set its Orientation
:
auto sp cppxaml::StackPanel({
cppxaml::TextBlock(L"Hello"),
cppxaml::TextBlock(L"world!").Name(L"worldTB")
}).Orientation(cppxaml::xaml::Controls::Orientation::Horizontal);
ContentControl (Button, etc.)
Sub-classes of XAML's ContentControl
enable nesting one control into another via the Content
property. CppXAML makes this easier:
auto scrollViewer = cppxaml::MakeContentControl<cppxaml::xaml::Controls::ScrollViewer>({
cppxaml::StackPanel({
cppxaml::TextBlock(L"Hello"),
cppxaml::TextBlock(L"world!").Name(L"worldTB")
})
});
Locating elements by name
Sometimes you will need to perform some operation on an element that is deeply nested in a fluent-style declaration. You can use FindChildByName
to find an element in a XAML tree with a given name:
auto worldTB = cppxaml::FindChildByName<Controls::TextBlock>(*scrollViewer, L"worldTB");
Grid
Declaring a Grid
in XAML via code is cumbersome as one has to create and set its RowDefinitions
and ColumnDefinitions
.
CppXAML makes this a lot more straightforward:
auto grid = cppxaml::Grid({"40, *"}, {"Auto, Auto"}, {
{0, 0, cppxaml::TextBlock(L"first") },
{0, 1, cppxaml::TextBlock(L"second") },
{1, 0, cppxaml::TextBlock(L"third") },
{1, 1, cppxaml::TextBlock(L"fourth") },
}),
Here we defined a 2x2 Grid
. The rows have heights of 40 px and *
, and the columns are Auto
. Then each child of the Grid is added in the cell designated by each entry in the initializer list, read as "row, column, child".
In addition to the string syntax (which requires some parsing/tokenizing), this also works:
auto grid = cppxaml::Grid({40, {"*"}}, {{"Auto"}, {"Auto"}}, {
{0, 0, cppxaml::TextBlock(L"first") },
{0, 1, cppxaml::TextBlock(L"second") },
{1, 0, cppxaml::TextBlock(L"third") },
{1, 1, cppxaml::TextBlock(L"fourth") },
}),
AutoSuggestBox
You can easily create an AutoSuggestBox
from a std::vector<std::wstring>
; make sure the vector's lifetime extends for at least as long as the XAML UI is up.
EnableDefaultSearch()
will provide a reasonable default search experience (filters the list of items down to those that contain the search string). This behavior is case insensitive by default, but can be made case sensitive by passing false
.
auto asb = cppxaml::AutoSuggestBox(GetFontFamilies())
.EnableDefaultSearch()
.Margin(0, 16, 0, 4)
.Name(L"fontTB");
Learn more about Target Frameworks and .NET Standard.
-
- Microsoft.Toolkit.Win32.UI.XamlApplication (>= 6.1.3)
- Microsoft.Windows.CppWinRT (>= 2.0.211028.7)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
0.0.21 | 372 | 3/18/2023 |
0.0.20 | 405 | 11/14/2022 |
0.0.19 | 335 | 11/13/2022 |
0.0.18 | 331 | 11/12/2022 |
0.0.17 | 476 | 9/23/2022 |
0.0.16 | 10,962 | 1/8/2022 |
0.0.15 | 261 | 1/8/2022 |
0.0.13 | 263 | 1/7/2022 |
0.0.12 | 280 | 1/7/2022 |
0.0.11 | 264 | 1/4/2022 |
0.0.10 | 270 | 12/28/2021 |
0.0.9 | 280 | 12/27/2021 |
0.0.8 | 287 | 12/26/2021 |
0.0.7 | 267 | 12/23/2021 |
0.0.6 | 255 | 12/22/2021 |
0.0.5 | 268 | 12/22/2021 |
0.0.4 | 274 | 12/14/2021 |
0.0.3 | 275 | 12/8/2021 |
0.0.2 | 420 | 12/8/2021 |
0.0.1 | 544 | 8/27/2021 |