Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Viktigt!
Viktiga begrepp och termer som stöder din förståelse av hur du använder och skapar körningsklasser med C++/WinRT finns i Använda API:er med C++/WinRT och Redigerings-API:er med C++/WinRT.
En av de mest kraftfulla funktionerna i Windows App SDK är flexibiliteten som användargränssnittsstacken tillhandahåller för att skapa anpassade kontroller baserat på XAML-kontrolltypen. XAML UI-ramverket innehåller funktioner som anpassade beroendeegenskaper och anslutna egenskaper och kontrollmallar, vilket gör det enkelt att skapa funktionsrika och anpassningsbara kontroller. Det här avsnittet beskriver stegen för att skapa en anpassad kontroll (mallad) med C++/WinRT.
Skapa en tom app (BgLabelControlApp)
Börja med att skapa ett nytt projekt i Microsoft Visual Studio. Skapa en tom app, paketerad (WinUI 3 i skrivbordsapp) för C++-projekt, ange namnet BgLabelControlApp och kontrollera (så att mappstrukturen ska överensstämma med genomgången) att Placera lösning och projekt i samma mapp inte är markerat. Rikta in dig på den senaste allmänt tillgängliga (dvs. inte förhandsversionen) av Windows SDK.
I ett senare avsnitt i det här avsnittet uppmanas du att skapa projektet (men bygg inte förrän då).
Note
Information om hur du konfigurerar Visual Studio för C++/WinRT-utveckling – inklusive installation och användning av VSIX (C++/WinRT Visual Studio Extension) och NuGet-paketet (som tillsammans tillhandahåller projektmall och byggstöd) – finns i Visual Studio stöd för C++/WinRT.
Vi ska skapa en ny klass som representerar en anpassad kontroll med mall. Vi redigerar och använder klassen i samma kompileringsenhet. Men vi vill kunna instansiera denna klass från XAML-kod, och därför kommer den att vara en runtime-klass. Och vi kommer att använda C++/WinRT för att både skapa och använda den.
Det första steget i att skapa en ny körningsklass är att lägga till ett nytt objekt av typen Midl File (.idl) i projektet. Ge den namnet BgLabelControl.idl. Ta bort standardinnehållet i BgLabelControl.idloch klistra in den här körningsklassdeklarationen.
// BgLabelControl.idl
namespace BgLabelControlApp
{
runtimeclass BgLabelControl : Microsoft.UI.Xaml.Controls.Control
{
BgLabelControl();
static Microsoft.UI.Xaml.DependencyProperty LabelProperty{ get; };
String Label;
}
}
Listan ovan visar det mönster som du följer när du deklarerar en beroendeegenskap (DP). Det finns två delar i varje DP. Först deklarerar du en skrivskyddad statisk egenskap av typen DependencyProperty. Den har namnet på din DP plus-egenskap. Du använder den här statiska egenskapen i implementeringen. För det andra deklarerar du en läs- och skrivbar instansegenskap med typen och namnet på din DP. Om du vill skapa en bifogad egenskap (i stället för en DP) kan du se kodexemplen i Anpassade kopplade egenskaper.
Note
Om du vill ha en DP av flyttalstyp anger du det så här double (Double i MIDL 3.0). Om du deklarerar och implementerar en DP av typen float (Single i MIDL) och sedan anger ett värde för dp i XAML-markering, resulterar det i felet Det gick inte att skapa en "Windows. Foundation.Single från texten "<NUMBER>".
Spara filen. Projektet går för närvarande inte att kompilera färdigt, men att bygga det nu är ändå meningsfullt eftersom det genererar de källkodsfiler i vilka du ska implementera runtime-klassen BgLabelControl. Så gå vidare och skapa nu (de byggfel som du kan förvänta dig att se i det här skedet har att göra med en "olöst extern symbol").
Under byggprocessen midl.exe körs verktyget för att skapa en Windows Runtime metadatafil (\BgLabelControlApp\Debug\BgLabelControlApp\Unmerged\BgLabelControl.winmd) som beskriver körningsklassen.
cppwinrt.exe Sedan körs verktyget för att generera källkodsfiler som stöder redigering och användning av körningsklassen. Dessa filer innehåller stubs för att komma igång med att implementera BgLabelControl-körningsklassen som du deklarerade i din IDL. Dessa stubs är \BgLabelControlApp\BgLabelControlApp\Generated Files\sources\BgLabelControl.h och BgLabelControl.cpp.
Kopiera stub-filerna BgLabelControl.h och BgLabelControl.cpp från \BgLabelControlApp\BgLabelControlApp\Generated Files\sources\ till projektmappen, som är \BgLabelControlApp\BgLabelControlApp\. I Prieskumník riešení kontrollerar du att Visa alla filer är aktiverat. Högerklicka på de stub-filer som du kopierade och klicka på Include In Project.
Du kommer att se en static_assert överst i BgLabelControl.h och BgLabelControl.cpp, som du måste ta bort. Nu kommer projektet att byggas.
Implementera den anpassade kontrollklassen BgLabelControl
Nu öppnar vi \BgLabelControlApp\BgLabelControlApp\BgLabelControl.h och BgLabelControl.cpp för att implementera vår körningsklass. I BgLabelControl.h ändrar du konstruktorn så att den anger nyckeln för standardstilen, implementerar Label och LabelProperty, lägger till en statisk händelsehanterare med namnet OnLabelChanged som hanterar ändringar av beroendeegenskapens värde och lägger till en privat medlem för att lagra det bakomliggande fältet för LabelProperty.
När du har lagt till dem ser det BgLabelControl.h ut så här. Du kan kopiera och klistra in den här kodlistan för att ersätta innehållet i BgLabelControl.h.
// BgLabelControl.h
#pragma once
#include "BgLabelControl.g.h"
namespace winrt::BgLabelControlApp::implementation
{
struct BgLabelControl : BgLabelControlT<BgLabelControl>
{
BgLabelControl() { DefaultStyleKey(winrt::box_value(L"BgLabelControlApp.BgLabelControl")); }
winrt::hstring Label()
{
return winrt::unbox_value<winrt::hstring>(GetValue(m_labelProperty));
}
void Label(winrt::hstring const& value)
{
SetValue(m_labelProperty, winrt::box_value(value));
}
static Microsoft::UI::Xaml::DependencyProperty LabelProperty() { return m_labelProperty; }
static void OnLabelChanged(Microsoft::UI::Xaml::DependencyObject const&, Microsoft::UI::Xaml::DependencyPropertyChangedEventArgs const&);
private:
static Microsoft::UI::Xaml::DependencyProperty m_labelProperty;
};
}
namespace winrt::BgLabelControlApp::factory_implementation
{
struct BgLabelControl : BgLabelControlT<BgLabelControl, implementation::BgLabelControl>
{
};
}
I BgLabelControl.cppdefinierar du de statiska medlemmarna så här. Du kan kopiera och klistra in den här kodlistan för att ersätta innehållet i BgLabelControl.cpp.
// BgLabelControl.cpp
#include "pch.h"
#include "BgLabelControl.h"
#include "BgLabelControl.g.cpp"
namespace winrt::BgLabelControlApp::implementation
{
Microsoft::UI::Xaml::DependencyProperty BgLabelControl::m_labelProperty =
Microsoft::UI::Xaml::DependencyProperty::Register(
L"Label",
winrt::xaml_typename<winrt::hstring>(),
winrt::xaml_typename<BgLabelControlApp::BgLabelControl>(),
Microsoft::UI::Xaml::PropertyMetadata{ winrt::box_value(L"default label"), Microsoft::UI::Xaml::PropertyChangedCallback{ &BgLabelControl::OnLabelChanged } }
);
void BgLabelControl::OnLabelChanged(Microsoft::UI::Xaml::DependencyObject const& d, Microsoft::UI::Xaml::DependencyPropertyChangedEventArgs const& /* e */)
{
if (BgLabelControlApp::BgLabelControl theControl{ d.try_as<BgLabelControlApp::BgLabelControl>() })
{
// Call members of the projected type via theControl.
BgLabelControlApp::implementation::BgLabelControl* ptr{ winrt::get_self<BgLabelControlApp::implementation::BgLabelControl>(theControl) };
// Call members of the implementation type via ptr.
}
}
}
I den här genomgången använder vi inte OnLabelChanged. Men det finns där så att du kan se hur du registrerar en beroendeegenskap med ett återanrop som anropas när egenskapen ändras. Implementeringen av OnLabelChanged visar också hur du hämtar en härledd projekterad typ från en basprojekterad typ (den basprojekterade typen är DependencyObject, i det här fallet). Och den visar hur du sedan hämtar en pekare till den typ som implementerar den projicerade typen. Den andra åtgärden är naturligtvis bara möjlig i det projekt som implementerar den projekterade typen (det vill säga: det projekt som implementerar körtidsklassen).
Note
Om du inte har installerat Windows SDK version 10.0.17763.0 (Windows 10 version 1809) eller senare måste du anropa winrt::from_abi i händelsehanteraren för beroendeegenskapen ovan, i stället för winrt::get_self.
Utforma standardformatet för BgLabelControl
I sin konstruktor anger BgLabelControl en standardstilnyckel för sig själv. Men vad är ett standardformat? En anpassad (mallbaserad) kontroll måste ha en standardstil som innehåller en standardmall för kontrollen, vilken den kan använda för att rendera sig själv om den som använder kontrollen inte anger en stil och/eller mall. I det här avsnittet lägger vi till en markeringsfil i projektet som innehåller vårt standardformat.
Kontrollera att Visa alla filer fortfarande är aktiverat (i Prieskumník riešení). Under projektnoden skapar du en ny mapp (inte ett filter, utan en mapp) och ger den namnet "Teman". Under Themeslägger du till ett nytt objekt av typen Visual C++>XAML XAML-vy> och ger det namnet "Generic.xaml". Mapp- och filnamnen måste vara så här för att XAML-ramverket ska kunna hitta standardformatet för en anpassad kontroll. Ta bort standardinnehållet i Generic.xaml och klistra in koden nedan.
<!-- \Themes\Generic.xaml -->
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:BgLabelControlApp">
<Style TargetType="local:BgLabelControl" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:BgLabelControl">
<Grid Width="100" Height="100" Background="{TemplateBinding Background}">
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{TemplateBinding Label}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
I det här fallet är den enda egenskap som standardstilen sätter kontrollmallen. Mallen består av en fyrkant (vars bakgrund är bunden till egenskapen Background som alla instanser av XAML-kontrolltypen har) och ett textelement (vars text är bunden till egenskapen BgLabelControl::Label dependency).
Lägga till en instans av BgLabelControl på huvudsidan för användargränssnittet
Öppna MainPage.xaml, som innehåller XAML-markering för vår huvudsida för användargränssnittet. Omedelbart efter elementet Button (inuti StackPanel) lägger du till följande markering.
<local:BgLabelControl Background="Red" Label="Hello, World!"/>
Lägg också till följande inkluderingsdirektiv MainPage.h så att MainPage-typen (en kombination av kompilering av XAML-markering och imperativ kod) är medveten om den anpassade BgLabelControl-kontrolltypen . Om du vill använda BgLabelControl- från en annan XAML-sida lägger du också till samma inkluderingsdirektiv i huvudfilen för den sidan. Eller så kan du bara lägga till ett enda inkluderingsdirektiv i den förkompilerade huvudfilen.
// MainPage.h
...
#include "BgLabelControl.h"
...
Skapa och kör nu projektet. Du ser att standardkontrollmallen är bunden till bakgrundspenseln och till etiketten för BgLabelControl-instansen i märkspråket.
Den här handledningen visade ett enkelt exempel på en anpassad, mallbaserad kontroll i C++/WinRT. Du kan utforma dina egna anpassade kontroller så avancerade och fullfjädrade du vill. En anpassad kontroll kan till exempel ha formen av något så komplicerat som ett redigerbart datarutnät, en videospelare eller en visualiserare av 3D-geometri.
Implementera åsidosättningsbara metoder, till exempel MeasureOverride och OnApplyTemplate
Se avsnittet i Anropa och åsidosätta bastypen med C++/WinRT.
Viktiga API:er
Relaterade ämnen
Windows developer