Předávání parametrů efektu jako připojených vlastností
Připojené vlastnosti lze použít k definování parametrů efektu, které reagují na změny vlastností modulu runtime. Tento článek ukazuje použití připojených vlastností k předání parametrů efektu a změně parametru za běhu.
Proces vytváření parametrů efektu, které reagují na změny vlastností modulu runtime, je následující:
- Vytvořte
static
třídu, která obsahuje připojenou vlastnost pro každý parametr, který se má předat efektu. - Přidejte do třídy další připojenou vlastnost, která bude použita k řízení přidání nebo odebrání efektu do ovládacího prvku, ke kterému bude třída připojena. Zajistěte, aby tato připojená vlastnost registrovala delegáta
propertyChanged
, který se spustí při změně hodnoty vlastnosti. - Vytvořte
static
getters a setter pro každou připojenou vlastnost. - Implementujte v delegátu logiku
propertyChanged
pro přidání a odebrání efektu. - Implementujte vnořenou třídu uvnitř
static
třídy pojmenovanou za efektem, která podtřídyRoutingEffect
třídy. Pro konstruktor volejte konstruktor základní třídy, předejte zřetězení názvu skupiny překladu a jedinečné ID, které bylo zadáno v každé třídě efektu specifické pro platformu.
Parametry se pak dají předat do efektu přidáním připojených vlastností a hodnot vlastností do příslušného ovládacího prvku. Parametry lze navíc změnit za běhu zadáním nové připojené hodnoty vlastnosti.
Poznámka:
Připojená vlastnost je speciální typ bindable vlastnost, definovaná v jedné třídě, ale připojena k jiným objektům, a rozpoznatelná v XAML jako atributy, které obsahují třídu a název vlastnosti oddělené tečkou. Další informace naleznete v tématu Připojené vlastnosti.
Ukázková aplikace ukazuje ShadowEffect
, že přidá stín k textu zobrazenému ovládacím Label
prvku. Kromě toho je možné změnit barvu stínu za běhu. Následující diagram znázorňuje zodpovědnosti jednotlivých projektů v ukázkové aplikaci spolu s relacemi mezi nimi:
Label
Ovládací prvek na dané HomePage
platformě je přizpůsobený LabelShadowEffect
v každém projektu specifickém pro platformu. Parametry jsou předány každému LabelShadowEffect
ShadowEffect
prostřednictvím připojených vlastností ve třídě. Každá LabelShadowEffect
třída je odvozena od PlatformEffect
třídy pro každou platformu. Výsledkem je přidání stínu do textu zobrazeného ovládacím Label
prvku, jak je znázorněno na následujících snímcích obrazovky:
Vytvoření parametrů efektu
Vytvoří static
se třída, která bude představovat parametry efektu, jak je znázorněno v následujícím příkladu kódu:
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")
{
}
}
}
Obsahuje ShadowEffect
pět připojených vlastností s static
getters a setter pro každou připojenou vlastnost. Čtyři z těchto vlastností představují parametry, které se mají předat jednotlivým platformám LabelShadowEffect
. Třída ShadowEffect
také definuje připojenou HasShadow
vlastnost, která se používá k řízení přidání nebo odebrání efektu k ovládacímu prvku, ke kterému ShadowEffect
je třída připojena. Tato připojená vlastnost registruje metodu OnHasShadowChanged
, která se spustí při změně hodnoty vlastnosti. Tato metoda přidá nebo odebere účinek na základě hodnoty HasShadow
připojené vlastnosti.
Vnořená LabelShadowEffect
třída, která podtřídy RoutingEffect
třídy, podporuje přidání a odebrání efektu. Třída RoutingEffect
představuje efekt nezávislý na platformě, který zabalí vnitřní efekt, který je obvykle specifický pro platformu. To zjednodušuje proces odebrání efektu, protože neexistuje žádný přístup k informacím o typu pro efekt specifický pro platformu. Konstruktor LabelShadowEffect
volá konstruktor základní třídy, který předává parametr skládající se zřetězení názvu skupiny překladu a jedinečné ID zadané pro každou třídu efektu specifické pro platformu. To umožňuje přidání a odebrání efektu OnHasShadowChanged
v metodě následujícím způsobem:
- Přidání efektu – nová instance objektu
LabelShadowEffect
je přidána do kolekce ovládacího prvkuEffects
. Tím se nahradí použitímEffect.Resolve
metody pro přidání efektu. - Odebrání efektu
LabelShadowEffect
– první instance kolekce ovládacího prvkuEffects
se načte a odebere.
Využívání efektu
Jednotlivé platformy LabelShadowEffect
je možné využívat přidáním připojených vlastností do Label
ovládacího prvku, jak je znázorněno v následujícím příkladu kódu XAML:
<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>
Ekvivalent Label
v jazyce C# je znázorněn v následujícím příkladu kódu:
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
Nastavením připojené vlastnosti spustíte true
metoduShadowEffect.OnHasShadowChanged
, která přidá nebo odebere LabelShadowEffect
ovládací prvekLabel
. V obou příkladech kódu poskytuje připojená ShadowEffect.Color
vlastnost hodnoty barev specifické pro platformu. Další informace naleznete v tématu Třída zařízení.
Kromě toho Button
umožňuje změnit barvu stínu za běhu. Button
Po kliknutí změní následující kód barvu stínu ShadowEffect.Color
nastavením připojené vlastnosti:
ShadowEffect.SetColor (label, Color.Teal);
Využívání efektu se stylem
Efekty, které lze využívat přidáním připojených vlastností do ovládacího prvku, mohou být také využity stylem. Následující příklad kódu XAML ukazuje explicitní styl stínového efektu, který lze použít u Label
ovládacích prvků:
<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>
Lze Style
použít na objekt Label
nastavením jeho Style
vlastnosti na Style
instanci pomocí StaticResource
rozšíření značek, jak je znázorněno v následujícím příkladu kódu:
<Label Text="Label Shadow Effect" ... Style="{StaticResource ShadowEffectStyle}" />
Další informace o stylech naleznete v tématu Styly.
Vytvoření efektu na jednotlivých platformách
Následující části diskutují o implementaci třídy specifické pro danou platformu LabelShadowEffect
.
Projekt pro iOS
Následující příklad kódu ukazuje implementaci LabelShadowEffect
projektu 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));
}
}
Metoda OnAttached
volá metody, které načítají připojené hodnoty vlastností pomocí ShadowEffect
getters a které nastaví Control.Layer
vlastnosti na hodnoty vlastnosti k vytvoření stínu. Tato funkce je zabalena do try
/catch
bloku v případě, že ovládací prvek, ke kterému je efekt připojen, nemá Control.Layer
vlastnosti. Metoda neposkytuje OnDetached
žádnou implementaci, protože není nutné vyčistit.
Reakce na změny vlastností
Pokud se některé z připojených ShadowEffect
hodnot vlastností změní za běhu, musí efekt reagovat zobrazením změn. Přepsáná verze metody, která je ve třídě efektu OnElementPropertyChanged
specifická pro platformu, je místo, kde můžete reagovat na změny vazebných vlastností, jak je znázorněno v následujícím příkladu kódu:
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 ();
}
}
...
}
Metoda OnElementPropertyChanged
aktualizuje poloměr, barvu nebo posun stínu za předpokladu, že se změnila příslušná ShadowEffect
hodnota připojené vlastnosti. Kontrola změněné vlastnosti by měla být vždy provedena, protože toto přepsání lze volat mnohokrát.
Android Project
Následující příklad kódu ukazuje implementaci LabelShadowEffect
projektu 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);
}
}
Metoda OnAttached
volá metody, které načítají připojené hodnoty vlastností pomocí ShadowEffect
getters, a volá metodu, která volá metodu TextView.SetShadowLayer
k vytvoření stínu pomocí hodnot vlastností. Tato funkce je zabalena do try
/catch
bloku v případě, že ovládací prvek, ke kterému je efekt připojen, nemá Control.Layer
vlastnosti. Metoda neposkytuje OnDetached
žádnou implementaci, protože není nutné vyčistit.
Reakce na změny vlastností
Pokud se některé z připojených ShadowEffect
hodnot vlastností změní za běhu, musí efekt reagovat zobrazením změn. Přepsáná verze metody, která je ve třídě efektu OnElementPropertyChanged
specifická pro platformu, je místo, kde můžete reagovat na změny vazebných vlastností, jak je znázorněno v následujícím příkladu kódu:
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 ();
}
}
...
}
Metoda OnElementPropertyChanged
aktualizuje poloměr, barvu nebo posun stínu za předpokladu, že se změnila příslušná ShadowEffect
hodnota připojené vlastnosti. Kontrola změněné vlastnosti by měla být vždy provedena, protože toto přepsání lze volat mnohokrát.
Univerzální platforma Windows Project
Následující příklad kódu ukazuje implementaci LabelShadowEffect
projektu Univerzální platforma Windows (UPW):
[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);
}
}
}
Univerzální platforma Windows neposkytuje stínový efekt, a proto LabelShadowEffect
implementace na obou platformách simuluje jeden přidáním druhého posunu Label
za primární Label
. Metoda OnAttached
vytvoří novou Label
a nastaví některé vlastnosti rozložení v objektu Label
. Potom volá metody, které načítají připojené hodnoty vlastností pomocí ShadowEffect
getters, a vytvoří stín nastavením TextColor
, TranslationX
a TranslationY
vlastnosti pro řízení barvy a umístění Label
. Potom shadowLabel
se vloží posun za primární Label
. Tato funkce je zabalena do try
/catch
bloku v případě, že ovládací prvek, ke kterému je efekt připojen, nemá Control.Layer
vlastnosti. Metoda neposkytuje OnDetached
žádnou implementaci, protože není nutné vyčistit.
Reakce na změny vlastností
Pokud se některé z připojených ShadowEffect
hodnot vlastností změní za běhu, musí efekt reagovat zobrazením změn. Přepsáná verze metody, která je ve třídě efektu OnElementPropertyChanged
specifická pro platformu, je místo, kde můžete reagovat na změny vazebných vlastností, jak je znázorněno v následujícím příkladu kódu:
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 ();
}
}
...
}
Metoda OnElementPropertyChanged
aktualizuje barvu nebo posun stínu za předpokladu, že se změnila příslušná ShadowEffect
hodnota připojené vlastnosti. Kontrola změněné vlastnosti by měla být vždy provedena, protože toto přepsání lze volat mnohokrát.
Shrnutí
Tento článek ukázal použití připojených vlastností k předání parametrů efektu a změně parametru za běhu. Připojené vlastnosti lze použít k definování parametrů efektu, které reagují na změny vlastností modulu runtime.