Udostępnij za pośrednictwem


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:

  1. Utwórz klasę static zawierającą dołączoną właściwość dla każdego parametru, który ma zostać przekazany do efektu.
  2. 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.
  3. Tworzenie static modułów pobierających i ustawiających dla każdej dołączonej właściwości.
  4. Zaimplementuj logikę w delegatzie, propertyChanged aby dodać i usunąć efekt.
  5. Zaimplementuj klasę zagnieżdżoną wewnątrz static klasy o nazwie po efektie, która klasy klasy jest podklasowana RoutingEffect . 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:

Obowiązki projektu efekt cienia

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:

Efekt cienia na każdej platformie

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 LabelShadowEffectplatformy . 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 kontrolki Effects . Zastępuje to użycie Effect.Resolve metody w celu dodania efektu.
  • Usuwanie efektu — pierwsze wystąpienie LabelShadowEffect kolekcji kontrolki Effects 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 trycatch/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 trycatch/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 Labelelementem 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 TextColorwłaściwości , TranslationXi TranslationY w celu kontrolowania koloru i lokalizacji Labelobiektu . Następnie shadowLabel wstawiono przesunięcie za podstawowym Labelelementem . Ta funkcja jest owinięta trycatch/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.