Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Az XAML-vezérlőhöz hatékonyan kötődő tulajdonságot megfigyelhető tulajdonságnak nevezzük. Ez az ötlet a megfigyelői mintaként ismert szoftvertervezési mintán alapul. Ez a témakör bemutatja, hogyan valósíthat meg megfigyelhető tulajdonságokat a C++/WinRT-ben, és hogyan kötheti hozzájuk az XAML-vezérlőket (a háttérinformációkért lásd : Adatkötés).
Fontos
Azokat az alapvető fogalmakat és kifejezéseket, amelyek támogatják a futtatókörnyezeti osztályok C+++/WinRT használatával történő felhasználásának és szerkesztésének megértését, olvassa el az API-k használata c++/WinRT-lel és Szerzői API-k c++/WinRT használatával című témakört.
Mit jelent a megfigyelhető tulajdonság?
Tegyük fel, hogy egy BookSku nevű futtatókörnyezeti osztálynak van egy Title nevű tulajdonsága. Ha a BookSku az INotifyPropertyChanged::P ropertyChanged eseményt emeli ki, amikor a Cím értéke megváltozik, akkor ez azt jelenti, hogy a Cím egy megfigyelhető tulajdonság. A BookSku viselkedése (az esemény emelése vagy nem emelése) határozza meg, hogy a tulajdonságai közül melyik észlelhető.
Az XAML-szövegelemek vagy vezérlőelemek ezekhez az eseményekhez kötődhetnek, és kezelhetik őket. Egy ilyen elem vagy vezérlőelem a frissített érték(ek) beolvasásával kezeli az eseményt, majd frissíti magát az új érték megjelenítéséhez.
Note
A C++/WinRT Visual Studio bővítmény (VSIX) és a NuGet-csomag telepítésével és használatával kapcsolatos információkért (amelyek együttesen nyújtanak projektsablont és buildtámogatást) lásd Visual Studio C++/WinRT támogatását.
Üres alkalmazás létrehozása (Könyvesbolt)
Először hozzon létre egy új projektet a Microsoft Visual Studióban. Hozzon létre egy Blank App, Packaged (WinUI 3 in Desktop) C++-projektet, és nevezze el Bookstore névre. Győződjön meg arról, hogy a Megoldás és projekt elhelyezése ugyanabban a könyvtárban nincs bejelölve. A Windows SDK legújabb általánosan elérhető (azaz nem előzetes verziójú) verzióját célozza meg.
Egy új osztályt fogunk létrehozni, amely egy megfigyelhető címtulajdonságú könyvet jelöl. Az osztályt ugyanabban a fordítási egységben hozzuk létre és használjuk. De az XAML-ből szeretnénk csatlakozni ehhez az osztályhoz, és ezért futtatókörnyezeti osztály lesz. És a C++/WinRT-t fogjuk használni mind a létrehozására, mind a használatára.
Az új futtatókörnyezeti osztály elkészítésének első lépése egy új Midl-fájl (.idl) elem hozzáadása a projekthez. Nevezze el az új elemet BookSku.idl. Törölje a modul alapértelmezett tartalmát BookSku.idl, és illessze be ezt a futtatókörnyezeti osztály deklarációját.
// BookSku.idl
namespace Bookstore
{
runtimeclass BookSku : Microsoft.UI.Xaml.Data.INotifyPropertyChanged
{
BookSku(String title);
String Title;
}
}
Note
A nézetmodell-osztályoknak – vagyis az alkalmazásban deklarált futtatókörnyezeti osztályoknak – nem kell alaposztályból származnia. Erre példa a Fent deklarált BookSku osztály. Implementál egy felületet, de nem származik alaposztályból.
Minden olyan futtatókörnyezeti osztályt, amelyet az alkalmazásban deklarál, amely nem alaposztályból származik, összeállítható osztálynak nevezzük. És vannak megkötések a összeállítható osztályok körül. Ahhoz, hogy egy alkalmazás megfeleltethesse a Visual Studio és a Microsoft Store által a beküldések ellenőrzéséhez használt Windows-alkalmazástanúsítvány-teszteket (és így ahhoz, hogy az alkalmazás sikeresen betölthető legyen a Microsoft Store-ba), a összeállítható osztálynak végül egy Windows-alaposztályból kell származnia. Ez azt jelenti, hogy az öröklési hierarchia gyökerénél lévő osztálynak egy Windows.* vagy Microsoft.* névtérből származó típusnak kell lennie. Ha valóban egy alaposztályból kell származtatnia egy futásidejű osztályt – például azért, hogy megvalósítson egy BindableBase osztályt, amelyből az összes nézetmodellje származhat –, akkor a Microsoft.UI.Xaml.DependencyObject osztályból származtathatja.
A nézetmodell a nézet absztrakciója, így közvetlenül a nézethez kötődik (az XAML-jelölőnyelvhez). Az adatmodellek az adatok absztrakciói, és csak a nézetmodellekből származnak, és nem kapcsolódnak közvetlenül az XAML-hez. Így az adatmodelleket nem futtatókörnyezeti osztályokként deklarálhatja, hanem A C++ szerkezetek vagy osztályok szerint. Ezeket nem kell deklarálni a MIDL-ben, és szabadon használhatja a kívánt öröklési hierarchiát.
Mentse a fájlt, és hozza létre a projektet. A build még nem lesz (teljesen) sikeres, de el fog végezni helyettünk néhány szükséges dolgot. Pontosabban a buildelési folyamat során az midl.exe eszköz egy Windows-futtatókörnyezet metaadatfájl létrehozásához fut, amely leírja a futtatókörnyezeti osztályt (a fájl a lemezre kerül a következő helyen\Bookstore\Debug\Bookstore\Unmerged\BookSku.winmd: ). Ezután az cppwinrt.exe eszköz futtatásával forráskódfájlokat hozhat létre a futtatókörnyezeti osztály létrehozásához és használatához. Ezek a fájlok olyan csonkokat tartalmaznak, amelyekkel megkezdheti az IDL-ben deklarált BookSku futtatókörnyezeti osztály implementálását. Mindjárt megtaláljuk őket a lemezen, de ezek a stubok: \Bookstore\Bookstore\Generated Files\sources\BookSku.h és BookSku.cpp.
Most kattintson a jobb gombbal a projektcsomópontra a Visual Studio, majd kattintson a Mappa megnyitása a Fájlkezelőben parancsra. Ezzel megnyitja a projektmappát a Fájlkezelőben. Most a \Bookstore\Bookstore\ mappa tartalmát kell látnia. Innen lépjen a \Generated Files\sources\ mappába, és másolja a csonkfájlokat BookSku.h és BookSku.cpp a vágólapra. Lépjen vissza a projektmappára (\Bookstore\Bookstore\), és illessze be az imént másolt két fájlt. Végül a Megoldáskezelő-ben a kijelölt projektcsomópontnál győződjön meg arról, hogy a Show All Files be van kapcsolva. Kattintson az egér jobb gombjával a másolt csonkfájlokra, majd válassza a Projektbe foglalás parancsot.
Implementálja a BookSku-t
Most nyissuk meg a \Bookstore\Bookstore\BookSku.h és a BookSku.cpp elemet, és valósítsuk meg a futásidejű osztályunkat. Először a BookSku.h és a BookSku.cpp tetején megjelenik egy static_assert, amit el kell távolítania.
Ezután végezze el ezeket a módosításokat itt: BookSku.h
- Az alapértelmezett konstruktorban cserélje le a(z)
= defaultelemet erre:= delete. Ennek az az oka, hogy nem szeretnénk alapértelmezett konstruktort. - Adjon hozzá egy privát tagot a címet tároló karakterlánc számára. Vegye figyelembe, hogy van egy konstruktorunk, amely winrt::hstring értéket vesz fel. Ez az érték a címsor.
- Adjon hozzá egy másik privát tagot ahhoz az eseményhez, amelyet a cím módosításakor emelünk ki.
Miután elvégezte ezeket a módosításokat, a(z) BookSku.h így fog kinézni.
// BookSku.h
#pragma once
#include "BookSku.g.h"
namespace winrt::Bookstore::implementation
{
struct BookSku : BookSkuT<BookSku>
{
BookSku() = delete;
BookSku(winrt::hstring const& title);
winrt::hstring Title();
void Title(winrt::hstring const& value);
winrt::event_token PropertyChanged(Microsoft::UI::Xaml::Data::PropertyChangedEventHandler const& value);
void PropertyChanged(winrt::event_token const& token);
private:
winrt::hstring m_title;
winrt::event<Microsoft::UI::Xaml::Data::PropertyChangedEventHandler> m_propertyChanged;
};
}
namespace winrt::Bookstore::factory_implementation
{
struct BookSku : BookSkuT<BookSku, implementation::BookSku>
{
};
}
A(z) BookSku.cpp helyen valósítsa meg a függvényeket így.
// BookSku.cpp
#include "pch.h"
#include "BookSku.h"
#include "BookSku.g.cpp"
namespace winrt::Bookstore::implementation
{
BookSku::BookSku(winrt::hstring const& title) : m_title{ title }
{
}
winrt::hstring BookSku::Title()
{
return m_title;
}
void BookSku::Title(winrt::hstring const& value)
{
if (m_title != value)
{
m_title = value;
m_propertyChanged(*this, Microsoft::UI::Xaml::Data::PropertyChangedEventArgs{ L"Title" });
}
}
winrt::event_token BookSku::PropertyChanged(Microsoft::UI::Xaml::Data::PropertyChangedEventHandler const& handler)
{
return m_propertyChanged.add(handler);
}
void BookSku::PropertyChanged(winrt::event_token const& token)
{
m_propertyChanged.remove(token);
}
}
A Címmutor függvényben ellenőrizzük, hogy az aktuális értéktől eltérő érték van-e beállítva. És ha igen, akkor frissítjük a címet, és az INotifyPropertyChanged::P ropertyChanged eseményt is előállítjuk egy olyan argumentummal, amely megegyezik a módosított tulajdonság nevével. Ez azért van, hogy a felhasználói felület (UI) tudja, melyik tulajdonság értékét szeretné újra lekérdezni.
A projekt most újra létrejön, ha ellenőrizni szeretné.
BookstoreViewModel deklarálása és implementálása
A fő XAML-oldal egy főnézeti modellhez fog kapcsolódni. Ez a nézetmodell több tulajdonsággal is rendelkezik, köztük a BookSku típus egyikével. Ebben a lépésben deklaráljuk és implementáljuk a főnézeti modell futtatókörnyezeti osztályát.
Adjon hozzá egy MIDL-fájl (.idl) nevű új BookstoreViewModel.idl elemet. Lásd még: A futtatókörnyezeti osztályok Midl-fájlokba (.idl) szervezése.
// BookstoreViewModel.idl
import "BookSku.idl";
namespace Bookstore
{
runtimeclass BookstoreViewModel
{
BookstoreViewModel();
BookSku BookSku{ get; };
}
}
Mentés és buildelés (a buildelés még nem fog teljesen sikerülni, de ennek az az oka, hogy újra létrehozzuk a csonkfájlokat).
Másolja BookstoreViewModel.h a BookstoreViewModel.cpp mappát a Generated Files\sources projektmappába, és vegye bele őket a projektbe. Nyissa meg ezeket a fájlokat (újra eltávolítva a static_assert elemet), és valósítsa meg a futásidejű osztályt az alább látható módon. Figyelje meg, hogy a(z) BookstoreViewModel.h fájlban belefoglaljuk a(z) BookSku.h elemet, amely deklarálja a(z) BookSku implementációs típusát (ami: winrt::Bookstore::implementation::BookSku). És eltávolítjuk a(z) = default-t az alapértelmezett konstruktorból.
Note
Az alábbi BookstoreViewModel.hBookstoreViewModel.cppfelsorolásban a kód bemutatja a m_bookSku adattag létrehozásának alapértelmezett módját. Ez az a módszer, amely a C++/WinRT első kiadására nyúlik vissza, és érdemes legalább ismerni a mintát. A C++/WinRT 2.0-s és újabb verziójával elérhető egy optimalizált építési forma, amely egységes szerkezetként ismert (lásd a híreket és a változásokat a C++/WinRT 2.0-s verziójában). A témakör későbbi részében bemutatunk egy példát az egységes szerkezetre.
// BookstoreViewModel.h
#pragma once
#include "BookstoreViewModel.g.h"
#include "BookSku.h"
namespace winrt::Bookstore::implementation
{
struct BookstoreViewModel : BookstoreViewModelT<BookstoreViewModel>
{
BookstoreViewModel();
Bookstore::BookSku BookSku();
private:
Bookstore::BookSku m_bookSku{ nullptr };
};
}
namespace winrt::Bookstore::factory_implementation
{
struct BookstoreViewModel : BookstoreViewModelT<BookstoreViewModel, implementation::BookstoreViewModel>
{
};
}
// BookstoreViewModel.cpp
#include "pch.h"
#include "BookstoreViewModel.h"
#include "BookstoreViewModel.g.cpp"
namespace winrt::Bookstore::implementation
{
BookstoreViewModel::BookstoreViewModel()
{
m_bookSku = winrt::make<Bookstore::implementation::BookSku>(L"Atticus");
}
Bookstore::BookSku BookstoreViewModel::BookSku()
{
return m_bookSku;
}
}
Note
A típus m_bookSku az előrejelzett típus (winrt::Bookstore::BookSku), és a winrt::make sablonparaméter a megvalósítás típusa (winrt::Bookstore::implementáció::BookSku). Ennek ellenére a make a leképezett típus egy példányát adja vissza.
A projekt most újra létrejön.
BookstoreViewModel típusú tulajdonság hozzáadása a MainPage-hez
Nyissa meg MainPage.idl, amely deklarálja a fő felhasználói felületi oldalt képviselő futtatókörnyezeti osztályt.
- Adjon hozzá egy
importdirektívát a(z)BookstoreViewModel.idlimportálásához. - Adjon hozzá egy MainViewModel nevű írásvédett tulajdonságot , amely BookstoreViewModel típusú.
- Távolítsa el a MyProperty tulajdonságot.
// MainPage.idl
import "BookstoreViewModel.idl";
namespace Bookstore
{
runtimeclass MainPage : Microsoft.UI.Xaml.Controls.Page
{
MainPage();
BookstoreViewModel MainViewModel{ get; };
}
}
Mentse a fájlt. A projekt még nem fog teljesen sikeresen felépíteni, de az építés most hasznos dolog, mert újragenerálja azokat a forráskódfájlokat, amelyekben a MainPage futtatókörnyezeti osztály implementálva van (\Bookstore\Bookstore\Generated Files\sources\MainPage.h és MainPage.cpp). Tehát folytassa, és építsen most. Az ebben a szakaszban várható buildelési hiba a "MainViewModel": nem tagja a "winrt::Bookstore::implementation::MainPage"-nek.
Ha kihagyja a(z) BookstoreViewModel.idl include utasítást (lásd a fenti MainPage.idl felsorolását), akkor a következő hiba jelenik meg: < várt a(z) „MainViewModel” közelében. Egy másik tipp, hogy ügyeljen arra, hogy minden típus ugyanabban a névtérben maradjon – abban a névtérben, amely a kódpéldákban látható.
A várt módon megjelenő hiba elhárításához most ki kell másolnia a MainViewModel tulajdonság elérőmetódus-csonkjait a generált fájlokból (\Bookstore\Bookstore\Generated Files\sources\MainPage.h és MainPage.cpp), majd be kell illesztenie őket a(z) \Bookstore\Bookstore\MainPage.h és MainPage.cpp fájlba. Ennek lépéseit a következő lépésekkel ismertetjük.
A(z) \Bookstore\Bookstore\MainPage.h részben hajtsa végre a következő lépéseket.
- Tartalmazza
BookstoreViewModel.h, amely deklarálja a BookstoreViewModel implementálási típusát (ami winrt::Bookstore::implementáció::BookstoreViewModel). - Adjon hozzá egy privát tagot a nézetmodell tárolásához. Vegye figyelembe, hogy a tulajdonság kiegészítő függvénye (és a tag m_mainViewModel) a BookstoreViewModel (azaz Bookstore::BookstoreViewModel) előrejelzett típusában van implementálva.
- A megvalósítási típus ugyanabban a projektben (fordítási egységben) található, mint az alkalmazás, ezért m_mainViewModel az std::nullptr_t konstruktor túlterhelésen keresztül építjük fel.
- Távolítsa el a MyProperty tulajdonságot.
Note
Az alábbi MainPage.hMainPage.cpplistaelemek párjában a kód bemutatja a m_mainViewModel adattag létrehozásának alapértelmezett módját. Az alábbi szakaszban egy egységes szerkezetű verziót mutatunk be.
// MainPage.h
...
#include "BookstoreViewModel.h"
...
namespace winrt::Bookstore::implementation
{
struct MainPage : MainPageT<MainPage>
{
MainPage();
Bookstore::BookstoreViewModel MainViewModel();
void ClickHandler(Windows::Foundation::IInspectable const&, Microsoft::UI::Xaml::RoutedEventArgs const&);
private:
Bookstore::BookstoreViewModel m_mainViewModel{ nullptr };
};
}
...
Az \Bookstore\Bookstore\MainPage.cppalábbi felsorolásban látható módon végezze el az alábbi módosításokat.
- Hívja meg a winrt::make parancsot (a BookstoreViewModel implementálási típusával együtt), hogy a tervezett BookstoreViewModel típus új példányát rendelje hozzá m_mainViewModel. Ahogy fent láttuk, a BookstoreViewModel konstruktor létrehoz egy új BookSku objektumot privát adattagként, és a címét kezdetben a következőre
L"Atticus"állítja. - A gomb eseménykezelőjében (ClickHandler) frissítse a könyv címét a közzétett címére.
- Implementálja a MainViewModel tulajdonság tartozékát.
- Távolítsa el a MyProperty tulajdonságot.
// MainPage.cpp
#include "pch.h"
#include "MainPage.h"
#include "MainPage.g.cpp"
using namespace winrt;
using namespace Microsoft::UI::Xaml;
namespace winrt::Bookstore::implementation
{
MainPage::MainPage()
{
m_mainViewModel = winrt::make<Bookstore::implementation::BookstoreViewModel>();
InitializeComponent();
}
void MainPage::ClickHandler(Windows::Foundation::IInspectable const& /* sender */, Microsoft::UI::Xaml::RoutedEventArgs const& /* args */)
{
MainViewModel().BookSku().Title(L"To Kill a Mockingbird");
}
Bookstore::BookstoreViewModel MainPage::MainViewModel()
{
return m_mainViewModel;
}
}
Egységes szerkezet
Egységes szerkezet használata winrt::make helyett, MainPage.h deklarálva és inicializálva m_mainViewModel egyetlen lépésben, az alább látható módon.
// MainPage.h
...
#include "BookstoreViewModel.h"
...
struct MainPage : MainPageT<MainPage>
{
...
private:
Bookstore::BookstoreViewModel m_mainViewModel;
};
...
Ezután a MainPage konstruktorban MainPage.cppnincs szükség a kódra m_mainViewModel = winrt::make<Bookstore::implementation::BookstoreViewModel>();.
Az egységes építésről és a kód példáiról további információt az egységes építés és a közvetlen megvalósítási hozzáférés engedélyezése című témakörben talál.
A gomb kötése a Cím tulajdonsághoz
Nyissa meg a MainPage.xamlfájlt, amely tartalmazza a fő felhasználói felület oldalának XAML jelölését. Ahogy az alábbi felsorolásban látható, távolítsa el a nevet a gombból, és módosítsa a Content tulajdonság értékét egy literálból egy kötési kifejezésre. Jegyezze fel a Mode=OneWay kötési kifejezés tulajdonságát (egyirányú a nézetmodelltől a felhasználói felületig). A tulajdonság nélkül a felhasználói felület nem válaszol a tulajdonság által módosított eseményekre.
<Button Click="ClickHandler" Content="{x:Bind MainViewModel.BookSku.Title, Mode=OneWay}"/>
Most építse fel és futtassa a projektet. Kattintson a gombra a Click eseménykezelő végrehajtásához. Ez a kezelő meghívja a könyv címmutátorfüggvényét; ez a mutáció eseményt hoz létre, amely tudatja a felhasználói felülettel, hogy a Cím tulajdonság megváltozott; és a gomb újra lekérdezi a tulajdonság értékét a saját tartalomértékének frissítéséhez.
A {Binding} korrektúrabővítmény használata C++/WinRT használatával
A C++/WinRT jelenleg kiadott verziójához a {Binding} jelölőbővítmény használatához implementálnia kell az ICustomPropertyProvider és az ICustomProperty interfészeket.
Elem–elem kötés
Egy XAML-elem tulajdonságát egy másik XAML-elem tulajdonságához kötheti. Íme egy példa arra, hogyan néz ez ki jelölőnyelvben.
<TextBox x:Name="myTextBox" />
<TextBlock Text="{x:Bind myTextBox.Text, Mode=OneWay}" />
A myTextBox nevű XAML-entitást csak olvasható tulajdonságként kell deklarálnia a MIDL-fájljában (.idl).
// MainPage.idl
runtimeclass MainPage : Microsoft.UI.Xaml.Controls.Page
{
MainPage();
Microsoft.UI.Xaml.Controls.TextBox myTextBox{ get; };
}
Itt van ennek a szükségnek az oka. Az XAML-fordító által érvényesítendő összes típus (beleértve a(z) {x:Bind} alkalmazásban használt típusokat is) Windows metaadatokból (WinMD) olvasható. Mindössze annyit kell tennie, hogy hozzáadja a csak olvasható tulajdonságot a MIDL-fájlhoz. Ne implementálja, mert az automatikusan létrehozott XAML-kód biztosítja a megvalósítást.
Objektumok használata XAML-jelölőnyelvből
Az XAML {x:Bind} jelölőbővítmény használatával felhasznált összes entitást nyilvánosan közzé kell tenni az IDL-ben. Továbbá, ha a XAML-jelölés egy másik, szintén a jelölésben szereplő elemre való hivatkozást tartalmaz, akkor az adott jelölés getterének jelen kell lennie az IDL-ben.
<Page x:Name="MyPage">
<StackPanel>
<CheckBox x:Name="UseCustomColorCheckBox" Content="Use custom color"
Click="UseCustomColorCheckBox_Click" />
<Button x:Name="ChangeColorButton" Content="Change color"
Click="{x:Bind ChangeColorButton_OnClick}"
IsEnabled="{x:Bind UseCustomColorCheckBox.IsChecked.Value, Mode=OneWay}"/>
</StackPanel>
</Page>
A ChangeColorButton elem a UseCustomColorCheckBox elemre hivatkozik kötéssel. Ezért az oldal IDL-jének deklarálnia kell egy UseCustomColorCheckBox nevű, csak olvasható tulajdonságot ahhoz, hogy az elérhető legyen az adatkötés számára.
A UseCustomColorCheckBox kattintási eseménykezelő delegáltja klasszikus XAML delegálási szintaxist használ, így nincs szükség bejegyzésre az IDL-ben; csak nyilvánosnak kell lennie a megvalósítási osztályban. Másrészt a ChangeColorButton egy kattintásos eseménykezelővel is rendelkezik {x:Bind} , amelynek az IDL-be is be kell lépnie.
runtimeclass MyPage : Microsoft.UI.Xaml.Controls.Page
{
MyPage();
// These members are consumed by binding.
void ChangeColorButton_OnClick();
Microsoft.UI.Xaml.Controls.CheckBox UseCustomColorCheckBox{ get; };
}
Nem kell implementációt megadnia a UseCustomColorCheckBox tulajdonsághoz. Az XAML kódgenerátor ezt teszi Az Ön számára.
Kötés logikai típushoz
Ezt diagnosztikai módban teheti meg:
<TextBlock Text="{Binding CanPair}"/>
C++/CX-ben a true vagy a false jelenik meg; C++/WinRT-ben viszont a Windows.Foundation.IReference`1<Boolean> jelenik meg.
Ehelyett használja a(z) x:Bind elemet, ha logikai értékhez köt.
<TextBlock Text="{x:Bind CanPair}"/>
A Windows implementációs kódtárak (WIL) használata
A Windows implementációs kódtárak (WIL) segítséget nyújtanak a köthető tulajdonságok írásának megkönnyítéséhez. Lásd : Értesítési tulajdonságok a WIL dokumentációjában.
Fontos API-k
Kapcsolódó témakörök
Windows developer