Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Important
Untuk konsep dan istilah penting yang mendukung pemahaman Anda tentang cara menggunakan dan menulis kelas runtime dengan C++/WinRT, lihat Menggunakan API dengan C++/WinRT dan API Penulis dengan C++/WinRT.
Salah satu fitur paling kuat dari SDK Aplikasi Windows adalah fleksibilitas yang disediakan tumpukan antarmuka pengguna (UI) untuk membuat kontrol kustom berdasarkan jenis Kontrol XAML. Kerangka kerja UI XAML menyediakan fitur seperti properti dependensi kustom dan properti terlampir, dan templat kontrol, yang memudahkan untuk membuat kontrol yang kaya fitur dan dapat disesuaikan. Topik ini memandu Anda melalui langkah-langkah untuk membuat kontrol kustom (templat) dengan C++/WinRT.
Membuat Aplikasi Kosong (BgLabelControlApp)
Mulailah dengan membuat proyek baru di Microsoft Visual Studio. Buat Aplikasi Kosong, Dikemas (WinUI 3 di Desktop) untuk proyek C++, atur namanya ke BgLabelControlApp, dan (sehingga struktur folder Anda akan cocok dengan panduan) pastikan bahwa Tempatkan solusi dan proyek di direktori yang sama tidak dicentang. Targetkan versi terbaru yang tersedia secara umum (yaitu, bukan pratinjau) dari SDK Windows.
Di bagian selanjutnya dari topik ini, Anda akan diarahkan untuk membangun proyek Anda (tetapi jangan membangun sampai saat itu).
Note
Untuk informasi tentang menyiapkan Visual Studio untuk pengembangan C++/WinRT—termasuk menginstal dan menggunakan C++/WinRT Visual Studio Extension (VSIX) dan paket NuGet (yang bersama-sama menyediakan templat proyek dan dukungan build)—lihat dukungan Visual Studio untuk C++/WinRT.
Kita akan menulis kelas baru untuk mewakili kontrol kustom (templat). Kami menulis dan mengonsumsi kelas dalam unit kompilasi yang sama. Tetapi kita ingin dapat membuat instans kelas ini dari markup XAML, dan untuk alasan itu itu akan menjadi kelas runtime. Dan kita akan menggunakan C++/WinRT baik untuk membuat maupun menggunakannya.
Langkah pertama dalam menulis kelas runtime baru adalah menambahkan item Midl File (.idl) baru ke proyek. Beri nama BgLabelControl.idl. Hapus konten default dari BgLabelControl.idl, lalu tempelkan deklarasi kelas runtime ini.
// BgLabelControl.idl
namespace BgLabelControlApp
{
runtimeclass BgLabelControl : Microsoft.UI.Xaml.Controls.Control
{
BgLabelControl();
static Microsoft.UI.Xaml.DependencyProperty LabelProperty{ get; };
String Label;
}
}
Daftar di atas menunjukkan pola yang Anda ikuti saat mendeklarasikan properti dependensi (DP). Ada dua bagian dari setiap DP. Pertama, Anda mendeklarasikan properti statis baca-saja dari jenis DependencyProperty. Namanya adalah nama DP Anda ditambah Property. Anda akan menggunakan properti statis ini dalam implementasi Anda. Kedua, Anda mendeklarasikan properti instance yang dapat dibaca dan ditulis dengan tipe dan nama DP Anda. Jika Anda ingin menulis properti terlampir (bukan DP), maka lihat contoh kode di Properti terlampir kustom.
Note
Jika Anda menginginkan DP dengan jenis floating-point, buatlah double (Double di MIDL 3.0). Mendeklarasikan dan menerapkan DP jenis float (Single di MIDL), lalu mengatur nilai untuk DP tersebut dalam markup XAML, menghasilkan kesalahan Gagal membuat 'Windows. Foundation.Single' dari teks '<NUMBER>'.
Simpan file tersebut. Proyek tidak akan dibangun hingga selesai saat ini, tetapi membangun sekarang adalah hal yang berguna untuk dilakukan karena menghasilkan file kode sumber tempat Anda akan mengimplementasikan kelas runtime BgLabelControl . Jadi, silakan lakukan build sekarang (error build yang kemungkinan akan Anda temui pada tahap ini terkait dengan "simbol eksternal yang tidak terselesaikan").
Selama proses build, midl.exe alat dijalankan untuk membuat file metadata Windows Runtime (\BgLabelControlApp\Debug\BgLabelControlApp\Unmerged\BgLabelControl.winmd) yang menjelaskan kelas runtime. Kemudian, alat cppwinrt.exe dijalankan untuk menghasilkan berkas kode sumber guna membantu Anda menulis dan menggunakan kelas runtime Anda. File-file ini termasuk stub untuk membuat Anda mulai menerapkan kelas runtime BgLabelControl yang Anda deklarasikan di IDL Anda. Stub-stub itu adalah \BgLabelControlApp\BgLabelControlApp\Generated Files\sources\BgLabelControl.h dan BgLabelControl.cpp.
Salin file BgLabelControl.h stub dan BgLabelControl.cpp dari \BgLabelControlApp\BgLabelControlApp\Generated Files\sources\ ke folder proyek, yaitu \BgLabelControlApp\BgLabelControlApp\. Di Penjelajah Solusi, pastikan Tampilkan Semua File diaktifkan. Klik kanan file stub yang Anda salin, dan klik Sertakan Dalam Project.
Anda akan melihat static_assert di bagian BgLabelControl.h atas dan BgLabelControl.cpp, yang harus Anda hapus. Sekarang proyek akan dibangun.
Menerapkan kelas kontrol kustom BgLabelControl
Sekarang, mari kita buka \BgLabelControlApp\BgLabelControlApp\BgLabelControl.h dan BgLabelControl.cpp terapkan kelas runtime kita. Di BgLabelControl.h, ubah konstruktor untuk mengatur kunci gaya default, terapkan Label dan LabelProperty, tambahkan penanganan aktivitas statis bernama OnLabelChanged untuk memproses perubahan pada nilai properti dependensi, dan tambahkan anggota privat untuk menyimpan bidang pendukung untuk LabelProperty.
Setelah menambahkan semuanya, BgLabelControl.h Anda akan terlihat seperti ini. Anda dapat menyalin dan menempelkan daftar kode ini untuk menggantikan konten 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>
{
};
}
Dalam BgLabelControl.cpp, tentukan anggota statis seperti ini. Anda dapat menyalin dan menempelkan daftar kode ini untuk menggantikan konten 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.
}
}
}
Dalam panduan ini, kita tidak akan menggunakan OnLabelChanged. Tetapi itu ada agar Anda dapat melihat cara mendaftarkan properti dependensi dengan callback saat properti berubah. Implementasi OnLabelChanged juga menunjukkan cara mendapatkan jenis proyeksi turunan dari jenis proyeksi dasar (jenis dasar yang diproyeksikan adalah DependencyObject, dalam hal ini). Dan itu menunjukkan bagaimana cara mendapatkan referensi ke tipe yang mengimplementasikan tipe yang diproyeksikan. Operasi kedua itu secara alami hanya akan dimungkinkan dalam proyek yang mengimplementasikan jenis yang diproyeksikan (yaitu, proyek yang mengimplementasikan kelas runtime).
Note
Jika Anda belum menginstal SDK Windows versi 10.0.17763.0 (Windows 10, versi 1809), atau yang lebih baru, maka Anda perlu memanggil winrt::from_abi di properti dependensi mengubah penanganan aktivitas di atas, alih-alih winrt::get_self.
Mendesain gaya default untuk BgLabelControl
Dalam konstruktornya, BgLabelControl menetapkan kunci gaya default untuk dirinya sendiri. Tapi apa itu gaya bawaan? Kontrol kustom (bertemplate) perlu memiliki gaya bawaan—yang berisi template kontrol bawaan—yang dapat digunakannya untuk merender dirinya sendiri jika pengguna kontrol tidak menetapkan gaya dan/atau template. Di bagian ini kita akan menambahkan file markup ke proyek yang berisi gaya default kita.
Pastikan Tampakkan Semua File masih aktif (dalam Penjelajah Solusi). Di bawah simpul proyek Anda, buat folder baru (bukan filter, tetapi folder) dan beri nama "Tema". Di bawah Themes, tambahkan item baru bertipe Visual C++>XAML>XAML View, dan beri nama "Generic.xaml". Nama folder dan file harus seperti ini agar kerangka kerja XAML menemukan gaya default untuk kontrol kustom. Hapus konten Generic.xamldefault , dan tempelkan markup di bawah ini.
<!-- \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>
Dalam hal ini, properti satu-satunya yang ditetapkan oleh gaya default adalah template kontrol. Templat terdiri dari persegi (yang latar belakangnya terikat ke properti Latar Belakang yang dimiliki semua instans jenis Kontrol XAML), dan elemen teks (yang teksnya terikat ke properti dependensi BgLabelControl::Label ).
Menambahkan instans BgLabelControl ke halaman UI utama
Buka MainPage.xaml, yang berisi markup XAML untuk halaman UI utama kami. Segera setelah elemen Tombol (di dalam StackPanel), tambahkan markup berikut.
<local:BgLabelControl Background="Red" Label="Hello, World!"/>
Selain itu, tambahkan direktif include berikut ke MainPage.h agar tipe MainPage (kombinasi kompilasi markup XAML dan kode imperatif) dapat mengenali tipe kontrol kustom BgLabelControl. Jika Anda ingin menggunakan BgLabelControl dari halaman XAML yang lain, tambahkan direktif include yang sama ke file header untuk halaman tersebut juga. Atau, sebagai alternatif, cukup letakkan satu direktif penyertaan dalam file header Anda yang telah dikompilasi sebelumnya.
// MainPage.h
...
#include "BgLabelControl.h"
...
Sekarang bangun dan jalankan proyek. Anda akan melihat bahwa templat kontrol default terikat pada kuas latar belakang dan label dari instans BgLabelControl dalam markup.
Panduan ini menunjukkan contoh sederhana kontrol kustom (templat) di C++/WinRT. Anda dapat membuat kontrol kustom Anda sendiri dengan fitur dan kemampuan selengkap yang Anda inginkan. Misalnya, kontrol kustom dapat mengambil bentuk sesuatu yang rumit sebagai kisi data yang dapat diedit, pemutar video, atau visualizer geometri 3D.
Menerapkan metode yang dapat diganti , seperti MeasureOverride dan OnApplyTemplate
Lihat bagian Memanggil dan mengganti tipe dasar Anda dengan C++/WinRT.
API penting
Topik terkait
Windows developer