Meneruskan Parameter Efek sebagai Properti Terlampir
Properti terlampir dapat digunakan untuk menentukan parameter efek yang merespons perubahan properti runtime. Artikel ini menunjukkan penggunaan properti terlampir untuk meneruskan parameter ke efek, dan mengubah parameter saat runtime.
Proses untuk membuat parameter efek yang merespons perubahan properti runtime adalah sebagai berikut:
- Buat
static
kelas yang berisi properti terlampir untuk setiap parameter yang akan diteruskan ke efek. - Tambahkan properti terlampir tambahan ke kelas yang akan digunakan untuk mengontrol penambahan atau penghapusan efek ke kontrol tempat kelas akan dilampirkan. Pastikan bahwa properti terlampir ini mendaftarkan
propertyChanged
delegasi yang akan dijalankan ketika nilai properti berubah. - Buat
static
getter dan setter untuk setiap properti terlampir. - Terapkan logika di
propertyChanged
delegasi untuk menambahkan dan menghapus efeknya. - Terapkan kelas berlapis di dalam
static
kelas, dinamai sesuai efek, yang mensubkelasRoutingEffect
kelas. Untuk konstruktor, panggil konstruktor kelas dasar, meneruskan perangkaian nama grup resolusi, dan ID unik yang ditentukan pada setiap kelas efek khusus platform.
Parameter kemudian dapat diteruskan ke efek dengan menambahkan properti terlampir, dan nilai properti, ke kontrol yang sesuai. Selain itu, parameter dapat diubah pada runtime dengan menentukan nilai properti terlampir baru.
Catatan
Properti terlampir adalah jenis properti khusus yang dapat diikat, didefinisikan dalam satu kelas tetapi dilampirkan ke objek lain, dan dapat dikenali dalam XAML sebagai atribut yang berisi kelas dan nama properti yang dipisahkan oleh titik. Untuk informasi selengkapnya, lihat Properti Terlampir.
Aplikasi sampel menunjukkan ShadowEffect
yang menambahkan bayangan ke teks yang Label
ditampilkan oleh kontrol. Selain itu, warna bayangan dapat diubah pada runtime. Diagram berikut mengilustrasikan tanggung jawab setiap proyek dalam aplikasi sampel, bersama dengan hubungan di antara mereka:
Label
Kontrol pada HomePage
disesuaikan oleh LabelShadowEffect
di setiap proyek khusus platform. Parameter diteruskan ke masing-masing LabelShadowEffect
melalui properti terlampir di ShadowEffect
kelas . Setiap LabelShadowEffect
kelas berasal dari PlatformEffect
kelas untuk setiap platform. Ini menghasilkan bayangan yang ditambahkan ke teks yang ditampilkan oleh Label
kontrol, seperti yang ditunjukkan pada cuplikan layar berikut:
Membuat Parameter Efek
Kelas static
harus dibuat untuk mewakili parameter efek, seperti yang ditunjukkan dalam contoh kode berikut:
public static class ShadowEffect
{
public static readonly BindableProperty HasShadowProperty =
BindableProperty.CreateAttached ("HasShadow", typeof(bool), typeof(ShadowEffect), false, propertyChanged: OnHasShadowChanged);
public static readonly BindableProperty ColorProperty =
BindableProperty.CreateAttached ("Color", typeof(Color), typeof(ShadowEffect), Color.Default);
public static readonly BindableProperty RadiusProperty =
BindableProperty.CreateAttached ("Radius", typeof(double), typeof(ShadowEffect), 1.0);
public static readonly BindableProperty DistanceXProperty =
BindableProperty.CreateAttached ("DistanceX", typeof(double), typeof(ShadowEffect), 0.0);
public static readonly BindableProperty DistanceYProperty =
BindableProperty.CreateAttached ("DistanceY", typeof(double), typeof(ShadowEffect), 0.0);
public static bool GetHasShadow (BindableObject view)
{
return (bool)view.GetValue (HasShadowProperty);
}
public static void SetHasShadow (BindableObject view, bool value)
{
view.SetValue (HasShadowProperty, value);
}
...
static void OnHasShadowChanged (BindableObject bindable, object oldValue, object newValue)
{
var view = bindable as View;
if (view == null) {
return;
}
bool hasShadow = (bool)newValue;
if (hasShadow) {
view.Effects.Add (new LabelShadowEffect ());
} else {
var toRemove = view.Effects.FirstOrDefault (e => e is LabelShadowEffect);
if (toRemove != null) {
view.Effects.Remove (toRemove);
}
}
}
class LabelShadowEffect : RoutingEffect
{
public LabelShadowEffect () : base ("MyCompany.LabelShadowEffect")
{
}
}
}
ShadowEffect
berisi lima properti terlampir, dengan static
getter dan setter untuk setiap properti terlampir. Empat properti ini mewakili parameter yang akan diteruskan ke setiap platform khusus LabelShadowEffect
. Kelas juga ShadowEffect
mendefinisikan HasShadow
properti terlampir yang digunakan untuk mengontrol penambahan atau penghapusan efek ke kontrol tempat ShadowEffect
kelas dilampirkan. Properti terlampir ini mendaftarkan OnHasShadowChanged
metode yang akan dijalankan ketika nilai properti berubah. Metode ini menambahkan atau menghapus efek berdasarkan nilai HasShadow
properti terlampir.
Kelas berlapis LabelShadowEffect
, yang mensubkelas RoutingEffect
kelas, mendukung penambahan dan penghapusan efek. Kelas ini RoutingEffect
mewakili efek independen platform yang membungkus efek dalam yang biasanya khusus platform. Ini menyederhanakan proses penghapusan efek, karena tidak ada akses waktu kompilasi ke informasi jenis untuk efek khusus platform. LabelShadowEffect
Konstruktor memanggil konstruktor kelas dasar, meneruskan parameter yang terdiri dari perangkaian nama grup resolusi, dan ID unik yang ditentukan pada setiap kelas efek khusus platform. Ini memungkinkan penambahan dan penghapusan efek dalam OnHasShadowChanged
metode , sebagai berikut:
- Penambahan efek – instans
LabelShadowEffect
baru ditambahkan ke koleksi kontrolEffects
. Ini menggantikan menggunakanEffect.Resolve
metode untuk menambahkan efek. - Penghapusan efek – instans
LabelShadowEffect
pertama dalam koleksi kontrolEffects
diambil dan dihapus.
Mengkonsumsi Efek
Setiap platform khusus LabelShadowEffect
dapat digunakan dengan menambahkan properti terlampir ke kontrol, seperti yang Label
ditunjukkan dalam contoh kode XAML berikut:
<Label Text="Label Shadow Effect" ...
local:ShadowEffect.HasShadow="true" local:ShadowEffect.Radius="5"
local:ShadowEffect.DistanceX="5" local:ShadowEffect.DistanceY="5">
<local:ShadowEffect.Color>
<OnPlatform x:TypeArguments="Color">
<On Platform="iOS" Value="Black" />
<On Platform="Android" Value="White" />
<On Platform="UWP" Value="Red" />
</OnPlatform>
</local:ShadowEffect.Color>
</Label>
Yang setara Label
dalam C# ditunjukkan dalam contoh kode berikut:
var label = new Label {
Text = "Label Shadow Effect",
...
};
Color color = Color.Default;
switch (Device.RuntimePlatform)
{
case Device.iOS:
color = Color.Black;
break;
case Device.Android:
color = Color.White;
break;
case Device.UWP:
color = Color.Red;
break;
}
ShadowEffect.SetHasShadow (label, true);
ShadowEffect.SetRadius (label, 5);
ShadowEffect.SetDistanceX (label, 5);
ShadowEffect.SetDistanceY (label, 5);
ShadowEffect.SetColor (label, color));
ShadowEffect.HasShadow
Mengatur properti terlampir untuk true
menjalankan ShadowEffect.OnHasShadowChanged
metode yang menambahkan atau menghapus ke LabelShadowEffect
Label
kontrol. Dalam kedua contoh kode, ShadowEffect.Color
properti terlampir menyediakan nilai warna khusus platform. Untuk informasi selengkapnya, lihat Kelas Perangkat.
Selain itu, memungkinkan Button
warna bayangan diubah pada runtime. Saat diklik Button
, kode berikut mengubah warna bayangan dengan mengatur ShadowEffect.Color
properti terlampir:
ShadowEffect.SetColor (label, Color.Teal);
Mengkonsumsi Efek dengan Gaya
Efek yang dapat dikonsumsi dengan menambahkan properti terlampir ke kontrol juga dapat dikonsumsi oleh gaya. Contoh kode XAML berikut menunjukkan gaya eksplisit untuk efek bayangan, yang dapat diterapkan ke Label
kontrol:
<Style x:Key="ShadowEffectStyle" TargetType="Label">
<Style.Setters>
<Setter Property="local:ShadowEffect.HasShadow" Value="True" />
<Setter Property="local:ShadowEffect.Radius" Value="5" />
<Setter Property="local:ShadowEffect.DistanceX" Value="5" />
<Setter Property="local:ShadowEffect.DistanceY" Value="5" />
</Style.Setters>
</Style>
Style
dapat diterapkan ke a Label
dengan mengatur propertinya Style
ke Style
instans menggunakan StaticResource
ekstensi markup, seperti yang ditunjukkan dalam contoh kode berikut:
<Label Text="Label Shadow Effect" ... Style="{StaticResource ShadowEffectStyle}" />
Untuk informasi selengkapnya tentang gaya, lihat Gaya.
Membuat Efek pada setiap Platform
Bagian berikut membahas implementasi LabelShadowEffect
kelas khusus platform.
Proyek iOS
Contoh kode berikut menunjukkan LabelShadowEffect
implementasi untuk proyek iOS:
[assembly:ResolutionGroupName ("MyCompany")]
[assembly:ExportEffect (typeof(LabelShadowEffect), "LabelShadowEffect")]
namespace EffectsDemo.iOS
{
public class LabelShadowEffect : PlatformEffect
{
protected override void OnAttached ()
{
try {
UpdateRadius ();
UpdateColor ();
UpdateOffset ();
Control.Layer.ShadowOpacity = 1.0f;
} catch (Exception ex) {
Console.WriteLine ("Cannot set property on attached control. Error: ", ex.Message);
}
}
protected override void OnDetached ()
{
}
...
void UpdateRadius ()
{
Control.Layer.ShadowRadius = (nfloat)ShadowEffect.GetRadius (Element);
}
void UpdateColor ()
{
Control.Layer.ShadowColor = ShadowEffect.GetColor (Element).ToCGColor ();
}
void UpdateOffset ()
{
Control.Layer.ShadowOffset = new CGSize (
(double)ShadowEffect.GetDistanceX (Element),
(double)ShadowEffect.GetDistanceY (Element));
}
}
Metode ini OnAttached
memanggil metode yang mengambil nilai properti terlampir menggunakan getter ShadowEffect
, dan yang mengatur Control.Layer
properti ke nilai properti untuk membuat bayangan. Fungsionalitas ini dibungkus dalam try
/catch
blok jika kontrol yang dilampirkan efek tidak memiliki Control.Layer
properti . Tidak ada implementasi yang disediakan oleh OnDetached
metode karena tidak diperlukan pembersihan.
Menanggapi Perubahan Properti
Jika salah ShadowEffect
satu nilai properti terlampir berubah pada runtime, efek perlu merespons dengan menampilkan perubahan. Versi OnElementPropertyChanged
metode yang ditimpa, di kelas efek khusus platform, adalah tempat untuk menanggapi perubahan properti yang dapat diikat, seperti yang ditunjukkan dalam contoh kode berikut:
public class LabelShadowEffect : PlatformEffect
{
...
protected override void OnElementPropertyChanged (PropertyChangedEventArgs args)
{
if (args.PropertyName == ShadowEffect.RadiusProperty.PropertyName) {
UpdateRadius ();
} else if (args.PropertyName == ShadowEffect.ColorProperty.PropertyName) {
UpdateColor ();
} else if (args.PropertyName == ShadowEffect.DistanceXProperty.PropertyName ||
args.PropertyName == ShadowEffect.DistanceYProperty.PropertyName) {
UpdateOffset ();
}
}
...
}
Metode ini OnElementPropertyChanged
memperbarui radius, warna, atau offset bayangan, asalkan nilai properti terlampir yang sesuai ShadowEffect
telah berubah. Pemeriksaan properti yang diubah harus selalu dilakukan, karena penimpaan ini dapat dipanggil berkali-kali.
Proyek Android
Contoh kode berikut menunjukkan LabelShadowEffect
implementasi untuk proyek Android:
[assembly:ResolutionGroupName ("MyCompany")]
[assembly:ExportEffect (typeof(LabelShadowEffect), "LabelShadowEffect")]
namespace EffectsDemo.Droid
{
public class LabelShadowEffect : PlatformEffect
{
Android.Widget.TextView control;
Android.Graphics.Color color;
float radius, distanceX, distanceY;
protected override void OnAttached ()
{
try {
control = Control as Android.Widget.TextView;
UpdateRadius ();
UpdateColor ();
UpdateOffset ();
UpdateControl ();
} catch (Exception ex) {
Console.WriteLine ("Cannot set property on attached control. Error: ", ex.Message);
}
}
protected override void OnDetached ()
{
}
...
void UpdateControl ()
{
if (control != null) {
control.SetShadowLayer (radius, distanceX, distanceY, color);
}
}
void UpdateRadius ()
{
radius = (float)ShadowEffect.GetRadius (Element);
}
void UpdateColor ()
{
color = ShadowEffect.GetColor (Element).ToAndroid ();
}
void UpdateOffset ()
{
distanceX = (float)ShadowEffect.GetDistanceX (Element);
distanceY = (float)ShadowEffect.GetDistanceY (Element);
}
}
Metode ini OnAttached
memanggil metode yang mengambil nilai properti terlampir menggunakan getter ShadowEffect
, dan memanggil metode yang memanggil TextView.SetShadowLayer
metode untuk membuat bayangan menggunakan nilai properti. Fungsionalitas ini dibungkus dalam try
/catch
blok jika kontrol yang dilampirkan efek tidak memiliki Control.Layer
properti . Tidak ada implementasi yang disediakan oleh OnDetached
metode karena tidak diperlukan pembersihan.
Menanggapi Perubahan Properti
Jika salah ShadowEffect
satu nilai properti terlampir berubah pada runtime, efek perlu merespons dengan menampilkan perubahan. Versi OnElementPropertyChanged
metode yang ditimpa, di kelas efek khusus platform, adalah tempat untuk menanggapi perubahan properti yang dapat diikat, seperti yang ditunjukkan dalam contoh kode berikut:
public class LabelShadowEffect : PlatformEffect
{
...
protected override void OnElementPropertyChanged (PropertyChangedEventArgs args)
{
if (args.PropertyName == ShadowEffect.RadiusProperty.PropertyName) {
UpdateRadius ();
UpdateControl ();
} else if (args.PropertyName == ShadowEffect.ColorProperty.PropertyName) {
UpdateColor ();
UpdateControl ();
} else if (args.PropertyName == ShadowEffect.DistanceXProperty.PropertyName ||
args.PropertyName == ShadowEffect.DistanceYProperty.PropertyName) {
UpdateOffset ();
UpdateControl ();
}
}
...
}
Metode ini OnElementPropertyChanged
memperbarui radius, warna, atau offset bayangan, asalkan nilai properti terlampir yang sesuai ShadowEffect
telah berubah. Pemeriksaan properti yang diubah harus selalu dilakukan, karena penimpaan ini dapat dipanggil berkali-kali.
Proyek Platform Windows Universal
Contoh kode berikut menunjukkan LabelShadowEffect
implementasi untuk proyek Platform Windows Universal (UWP):
[assembly: ResolutionGroupName ("MyCompany")]
[assembly: ExportEffect (typeof(LabelShadowEffect), "LabelShadowEffect")]
namespace EffectsDemo.UWP
{
public class LabelShadowEffect : PlatformEffect
{
Label shadowLabel;
bool shadowAdded = false;
protected override void OnAttached ()
{
try {
if (!shadowAdded) {
var textBlock = Control as Windows.UI.Xaml.Controls.TextBlock;
shadowLabel = new Label ();
shadowLabel.Text = textBlock.Text;
shadowLabel.FontAttributes = FontAttributes.Bold;
shadowLabel.HorizontalOptions = LayoutOptions.Center;
shadowLabel.VerticalOptions = LayoutOptions.CenterAndExpand;
UpdateColor ();
UpdateOffset ();
((Grid)Element.Parent).Children.Insert (0, shadowLabel);
shadowAdded = true;
}
} catch (Exception ex) {
Debug.WriteLine ("Cannot set property on attached control. Error: ", ex.Message);
}
}
protected override void OnDetached ()
{
}
...
void UpdateColor ()
{
shadowLabel.TextColor = ShadowEffect.GetColor (Element);
}
void UpdateOffset ()
{
shadowLabel.TranslationX = ShadowEffect.GetDistanceX (Element);
shadowLabel.TranslationY = ShadowEffect.GetDistanceY (Element);
}
}
}
Platform Windows Universal tidak memberikan efek bayangan, sehingga LabelShadowEffect
implementasi pada kedua platform mensimulasikan satu dengan menambahkan offset Label
kedua di belakang primer Label
. Metode OnAttached
ini membuat baru Label
dan mengatur beberapa properti tata letak pada Label
. Kemudian memanggil metode yang mengambil nilai properti terlampir menggunakan getter ShadowEffect
, dan membuat bayangan dengan mengatur TextColor
properti , , TranslationX
dan TranslationY
untuk mengontrol warna dan lokasi Label
. shadowLabel
kemudian dimasukkan offset di belakang primer Label
. Fungsionalitas ini dibungkus dalam try
/catch
blok jika kontrol yang dilampirkan efek tidak memiliki Control.Layer
properti . Tidak ada implementasi yang disediakan oleh OnDetached
metode karena tidak diperlukan pembersihan.
Menanggapi Perubahan Properti
Jika salah ShadowEffect
satu nilai properti terlampir berubah pada runtime, efek perlu merespons dengan menampilkan perubahan. Versi OnElementPropertyChanged
metode yang ditimpa, di kelas efek khusus platform, adalah tempat untuk menanggapi perubahan properti yang dapat diikat, seperti yang ditunjukkan dalam contoh kode berikut:
public class LabelShadowEffect : PlatformEffect
{
...
protected override void OnElementPropertyChanged (PropertyChangedEventArgs args)
{
if (args.PropertyName == ShadowEffect.ColorProperty.PropertyName) {
UpdateColor ();
} else if (args.PropertyName == ShadowEffect.DistanceXProperty.PropertyName ||
args.PropertyName == ShadowEffect.DistanceYProperty.PropertyName) {
UpdateOffset ();
}
}
...
}
Metode memperbarui OnElementPropertyChanged
warna atau offset bayangan, asalkan nilai properti terlampir yang sesuai ShadowEffect
telah berubah. Pemeriksaan properti yang diubah harus selalu dilakukan, karena penimpaan ini dapat dipanggil berkali-kali.
Ringkasan
Artikel ini telah menunjukkan menggunakan properti terlampir untuk meneruskan parameter ke efek, dan mengubah parameter saat runtime. Properti terlampir dapat digunakan untuk menentukan parameter efek yang merespons perubahan properti runtime.