Przekazywanie parametrów efektu jako dołączonych właściwości
Dołączone właściwości mogą służyć do definiowania parametrów efektu, które reagują na zmiany właściwości środowiska uruchomieniowego. W tym artykule pokazano użycie dołączonych właściwości w celu przekazania parametrów do efektu i zmiany parametru w czasie wykonywania.
Proces tworzenia parametrów efektu, które reagują na zmiany właściwości środowiska uruchomieniowego, jest następujący:
- Utwórz klasę
static
zawierającą dołączoną właściwość dla każdego parametru, który ma zostać przekazany do efektu. - Dodaj dodatkową dołączoną właściwość do klasy, która będzie używana do kontrolowania dodawania lub usuwania efektu do kontrolki, do którego zostanie dołączona klasa. Upewnij się, że ta dołączona właściwość rejestruje
propertyChanged
delegata, który zostanie wykonany po zmianie wartości właściwości. - Tworzenie
static
modułów pobierających i ustawiających dla każdej dołączonej właściwości. - Zaimplementuj logikę w delegatzie,
propertyChanged
aby dodać i usunąć efekt. - Zaimplementuj klasę zagnieżdżoną wewnątrz
static
klasy o nazwie po efektie, która klasy klasy jest podklasowanaRoutingEffect
. W przypadku konstruktora wywołaj konstruktor klasy bazowej, przekazując połączenie nazwy grupy rozpoznawania i unikatowy identyfikator, który został określony w każdej klasie efektu specyficznego dla platformy.
Parametry można następnie przekazać do efektu, dodając dołączone właściwości i wartości właściwości do odpowiedniej kontrolki. Ponadto parametry można zmienić w czasie wykonywania, określając nową dołączoną wartość właściwości.
Uwaga
Dołączona właściwość jest specjalnym typem właściwości możliwej do powiązania, zdefiniowaną w jednej klasie, ale dołączoną do innych obiektów i rozpoznawalną w języku XAML jako atrybutami, które zawierają klasę i nazwę właściwości oddzieloną kropką. Aby uzyskać więcej informacji, zobacz Dołączone właściwości.
Przykładowa aplikacja demonstruje element ShadowEffect
, który dodaje cień do tekstu wyświetlanego przez kontrolkę Label
. Ponadto kolor cienia można zmienić w czasie wykonywania. Na poniższym diagramie przedstawiono obowiązki każdego projektu w przykładowej aplikacji wraz z relacjami między nimi:
Kontrolka Label
na obiekcie HomePage
jest dostosowywana przez LabelShadowEffect
element w każdym projekcie specyficznym dla platformy. Parametry są przekazywane do każdej LabelShadowEffect
z dołączonych właściwości w ShadowEffect
klasie. Każda LabelShadowEffect
klasa pochodzi z PlatformEffect
klasy dla każdej platformy. Spowoduje to dodanie cienia do tekstu wyświetlanego przez kontrolkę Label
, jak pokazano na poniższych zrzutach ekranu:
Tworzenie parametrów efektu
Należy utworzyć klasę static
reprezentującą parametry efektu, jak pokazano w poniższym przykładzie kodu:
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")
{
}
}
}
Zawiera ShadowEffect
pięć dołączonych właściwości z metodami static
getters i setters dla każdej dołączonej właściwości. Cztery z tych właściwości reprezentują parametry, które mają być przekazywane do poszczególnych platform specyficznych dla LabelShadowEffect
platformy . Klasa ShadowEffect
definiuje również dołączoną HasShadow
właściwość, która służy do kontrolowania dodawania lub usuwania efektu do kontrolki, do którego ShadowEffect
jest dołączona klasa. Ta dołączona właściwość rejestruje metodę OnHasShadowChanged
, która zostanie wykonana po zmianie wartości właściwości. Ta metoda dodaje lub usuwa efekt na podstawie wartości dołączonej HasShadow
właściwości.
Zagnieżdżona LabelShadowEffect
klasa, która podklasuje klasę RoutingEffect
, obsługuje dodawanie i usuwanie efektów. Klasa RoutingEffect
reprezentuje efekt niezależny od platformy, który opakowuje efekt wewnętrzny, który jest zwykle specyficzny dla platformy. Upraszcza to proces usuwania efektu, ponieważ nie ma dostępu w czasie kompilacji do informacji o typie dla efektu specyficznego dla platformy. Konstruktor LabelShadowEffect
wywołuje konstruktor klasy bazowej, przekazując parametr składający się z łączenia nazwy grupy rozpoznawania i unikatowy identyfikator określony w każdej klasie efektów specyficznych dla platformy. Umożliwia to dodanie i usunięcie efektu w metodzie OnHasShadowChanged
w następujący sposób:
- Dodawanie efektu — nowe wystąpienie kontrolki
LabelShadowEffect
jest dodawane do kolekcji kontrolkiEffects
. Zastępuje to użycieEffect.Resolve
metody w celu dodania efektu. - Usuwanie efektu — pierwsze wystąpienie
LabelShadowEffect
kolekcji kontrolkiEffects
jest pobierane i usuwane.
Korzystanie z efektu
Poszczególne platformy LabelShadowEffect
mogą być używane przez dodanie dołączonych właściwości do Label
kontrolki, jak pokazano w poniższym przykładzie kodu 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>
Odpowiednik Label
w języku C# jest pokazany w poniższym przykładzie kodu:
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));
Ustawienie dołączonej ShadowEffect.HasShadow
właściwości w celu true
wykonania ShadowEffect.OnHasShadowChanged
metody, która dodaje lub usuwa LabelShadowEffect
element do kontrolki Label
. W obu przykładach ShadowEffect.Color
kodu dołączona właściwość udostępnia wartości kolorów specyficznych dla platformy. Aby uzyskać więcej informacji, zobacz Klasa urządzenia.
Ponadto element umożliwia Button
zmianę koloru cienia w czasie wykonywania. Po kliknięciu Button
elementu poniższy kod zmienia kolor cienia, ustawiając dołączoną ShadowEffect.Color
właściwość:
ShadowEffect.SetColor (label, Color.Teal);
Korzystanie z efektu za pomocą stylu
Efekty, które mogą być używane przez dodanie dołączonych właściwości do kontrolki, mogą być również używane przez styl. Poniższy przykład kodu XAML przedstawia jawny styl efektu cienia, który można zastosować do Label
kontrolek:
<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>
Można Style
go zastosować, Label
ustawiając jego Style
właściwość na Style
wystąpienie przy użyciu StaticResource
rozszerzenia znaczników, jak pokazano w poniższym przykładzie kodu:
<Label Text="Label Shadow Effect" ... Style="{StaticResource ShadowEffectStyle}" />
Aby uzyskać więcej informacji na temat stylów, zobacz Style.
Tworzenie wpływu na każdą platformę
W poniższych sekcjach omówiono implementację klasy specyficznej dla platformy LabelShadowEffect
.
Projekt systemu iOS
Poniższy przykład kodu przedstawia implementację LabelShadowEffect
projektu systemu 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
wywołuje metody pobierające dołączone wartości właściwości przy użyciu ShadowEffect
metod pobierania i ustawiające Control.Layer
właściwości na wartości właściwości w celu utworzenia cienia. Ta funkcja jest owinięta try
catch
/w bloku, jeśli kontrolka, do którego jest dołączony efekt, nie ma Control.Layer
właściwości. Żadna implementacja nie jest dostarczana przez metodę OnDetached
, ponieważ nie jest konieczne czyszczenie.
Reagowanie na zmiany właściwości
Jeśli którakolwiek z dołączonych ShadowEffect
wartości właściwości zmieni się w czasie wykonywania, efekt musi odpowiadać, wyświetlając zmiany. Przesłoniętą wersję OnElementPropertyChanged
metody w klasie efektu specyficznego dla platformy jest miejscem reagowania na zmiany właściwości, które można powiązać, jak pokazano w poniższym przykładzie kodu:
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 promień, kolor lub przesunięcie cienia, pod warunkiem że zmieniono odpowiednią ShadowEffect
dołączoną wartość właściwości. Należy zawsze sprawdzić zmienioną właściwość, ponieważ to zastąpienie może być wywoływane wiele razy.
Projekt systemu Android
Poniższy przykład kodu przedstawia implementację LabelShadowEffect
projektu systemu 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
wywołuje metody, które pobierają dołączone wartości właściwości przy użyciu ShadowEffect
metod getters i wywołuje metodę, która TextView.SetShadowLayer
wywołuje metodę w celu utworzenia cienia przy użyciu wartości właściwości. Ta funkcja jest owinięta try
catch
/w bloku, jeśli kontrolka, do którego jest dołączony efekt, nie ma Control.Layer
właściwości. Żadna implementacja nie jest dostarczana przez metodę OnDetached
, ponieważ nie jest konieczne czyszczenie.
Reagowanie na zmiany właściwości
Jeśli którakolwiek z dołączonych ShadowEffect
wartości właściwości zmieni się w czasie wykonywania, efekt musi odpowiadać, wyświetlając zmiany. Przesłoniętą wersję OnElementPropertyChanged
metody w klasie efektu specyficznego dla platformy jest miejscem reagowania na zmiany właściwości, które można powiązać, jak pokazano w poniższym przykładzie kodu:
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 promień, kolor lub przesunięcie cienia, pod warunkiem że zmieniono odpowiednią ShadowEffect
dołączoną wartość właściwości. Należy zawsze sprawdzić zmienioną właściwość, ponieważ to zastąpienie może być wywoływane wiele razy.
projekt platforma uniwersalna systemu Windows
Poniższy przykład kodu przedstawia implementację LabelShadowEffect
projektu platforma uniwersalna systemu Windows (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);
}
}
}
Platforma uniwersalna systemu Windows nie zapewnia efektu cienia, dlatego LabelShadowEffect
implementacja na obu platformach symuluje jedno przez dodanie drugiego przesunięcia za podstawowym Label
elementem Label
. Metoda OnAttached
tworzy nowe Label
i ustawia niektóre właściwości układu na obiekcie Label
. Następnie wywołuje metody, które pobierają dołączone wartości właściwości przy użyciu ShadowEffect
metod getters i tworzą cień, ustawiając TextColor
właściwości , TranslationX
i TranslationY
w celu kontrolowania koloru i lokalizacji Label
obiektu . Następnie shadowLabel
wstawiono przesunięcie za podstawowym Label
elementem . Ta funkcja jest owinięta try
catch
/w bloku, jeśli kontrolka, do którego jest dołączony efekt, nie ma Control.Layer
właściwości. Żadna implementacja nie jest dostarczana przez metodę OnDetached
, ponieważ nie jest konieczne czyszczenie.
Reagowanie na zmiany właściwości
Jeśli którakolwiek z dołączonych ShadowEffect
wartości właściwości zmieni się w czasie wykonywania, efekt musi odpowiadać, wyświetlając zmiany. Przesłoniętą wersję OnElementPropertyChanged
metody w klasie efektu specyficznego dla platformy jest miejscem reagowania na zmiany właściwości, które można powiązać, jak pokazano w poniższym przykładzie kodu:
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 kolor lub przesunięcie cienia, pod warunkiem że zmieniono odpowiednią ShadowEffect
dołączoną wartość właściwości. Należy zawsze sprawdzić zmienioną właściwość, ponieważ to zastąpienie może być wywoływane wiele razy.
Podsumowanie
W tym artykule pokazano użycie dołączonych właściwości w celu przekazania parametrów do efektu i zmiany parametru w czasie wykonywania. Dołączone właściwości mogą służyć do definiowania parametrów efektu, które reagują na zmiany właściwości środowiska uruchomieniowego.