Passando parâmetros de efeito como propriedades anexadasPassing Effect Parameters as Attached Properties

Baixar Exemplo Baixar o exemploDownload Sample Download the sample

Propriedades anexadas podem ser usadas para definir parâmetros de efeito que respondem a alterações de propriedade de tempo de execução. Este artigo demonstra o uso de propriedades anexadas para passar parâmetros para um efeito e a alteração de um parâmetro em tempo de execução.Attached properties can be used to define effect parameters that respond to runtime property changes. This article demonstrates using attached properties to pass parameters to an effect, and changing a parameter at runtime.

O processo para criar parâmetros de efeito que respondem a alterações de propriedade de tempo de execução é o seguinte:The process for creating effect parameters that respond to runtime property changes is as follows:

  1. Crie uma classe static que contém uma propriedade anexada para cada parâmetro a ser passado para o efeito.Create a static class that contains an attached property for each parameter to be passed to the effect.
  2. Adicione outra propriedade anexada à classe que será usada para controlar a adição ou remoção do efeito para o controle a que a classe será anexada.Add an additional attached property to the class that will be used to control the addition or removal of the effect to the control that the class will be attached to. Certifique-se de que a propriedade anexada registre um delegado propertyChanged que será executado quando o valor da propriedade for alterado.Ensure that this attached property registers a propertyChanged delegate that will be executed when the value of the property changes.
  3. Crie getters e setters static para cada propriedade anexada.Create static getters and setters for each attached property.
  4. Implemente a lógica no delegado propertyChanged para adicionar e remover o efeito.Implement logic in the propertyChanged delegate to add and remove the effect.
  5. Implemente uma classe aninhada dentro da classe static, com o mesmo nome do efeito, que cria uma subclasse da classe RoutingEffect.Implement a nested class inside the static class, named after the effect, which subclasses the RoutingEffect class. Para o construtor, chame o construtor da classe base passando uma concatenação do nome do grupo de resolução e a ID exclusiva que foi especificada em cada classe de efeito específica da plataforma.For the constructor, call the base class constructor, passing in a concatenation of the resolution group name, and the unique ID that was specified on each platform-specific effect class.

Em seguida, é possível passar parâmetros para o efeito adicionando as propriedades anexadas e valores de propriedade ao controle apropriado.Parameters can then be passed to the effect by adding the attached properties, and property values, to the appropriate control. Além disso, os parâmetros podem ser alterados no tempo de execução especificando um novo valor da propriedade anexada.In addition, parameters can be changed at runtime by specifying a new attached property value.

Observação

Uma propriedade anexada é um tipo especial de propriedade associável, definida em uma classe, mas anexada a outros objetos e reconhecível no XAML como atributos que contêm uma classe e um nome de propriedade separados por um ponto.An attached property is a special type of bindable property, defined in one class but attached to other objects, and recognizable in XAML as attributes that contain a class and a property name separated by a period. Para obter mais informações, confira Propriedades anexadas.For more information, see Attached Properties.

O aplicativo de exemplo demonstra um ShadowEffect que adiciona uma sombra ao texto exibido por um controle Label.The sample application demonstrates a ShadowEffect that adds a shadow to the text displayed by a Label control. Além disso, a cor da sombra pode ser alterada em tempo de execução.In addition, the color of the shadow can be changed at runtime. O diagrama a seguir ilustra as responsabilidades de cada projeto no aplicativo de exemplo, bem como as relações entre elas:The following diagram illustrates the responsibilities of each project in the sample application, along with the relationships between them:

Um controle Label no HomePage é personalizado pelo LabelShadowEffect em cada projeto específico da plataforma.A Label control on the HomePage is customized by the LabelShadowEffect in each platform-specific project. Os parâmetros são passados para cada LabelShadowEffect por meio das propriedades anexadas na classe ShadowEffect.Parameters are passed to each LabelShadowEffect through attached properties in the ShadowEffect class. Cada classe LabelShadowEffect é derivada da classe PlatformEffect de cada plataforma.Each LabelShadowEffect class derives from the PlatformEffect class for each platform. Isso faz com que uma sombra seja adicionada ao texto exibido pelo controle Label, conforme mostrado nas capturas de tela seguir:This results in a shadow being added to the text displayed by the Label control, as shown in the following screenshots:

Criando parâmetros de efeitoCreating Effect Parameters

Uma classe static deve ser criada para representar os parâmetros em vigor, conforme demonstrado no exemplo de código a seguir:A static class should be created to represent effect parameters, as demonstrated in the following code example:

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")
    {
    }
  }
}

O ShadowEffect contém cinco propriedades anexadas, com getters e setters static para cada propriedade anexada.The ShadowEffect contains five attached properties, with static getters and setters for each attached property. Quatro dessas propriedades representam parâmetros a serem passados para cada LabelShadowEffect específico da plataforma.Four of these properties represent parameters to be passed to each platform-specific LabelShadowEffect. A classe ShadowEffect também define uma propriedade anexada HasShadow que é usada para controlar a adição ou remoção do efeito para o controle a que a classe ShadowEffect é anexada.The ShadowEffect class also defines a HasShadow attached property that is used to control the addition or removal of the effect to the control that the ShadowEffect class is attached to. Essa propriedade anexada registra o método OnHasShadowChanged que será executado quando o valor da propriedade for alterado.This attached property registers the OnHasShadowChanged method that will be executed when the value of the property changes. Esse método adiciona ou remove o efeito com base no valor da propriedade anexada HasShadow.This method adds or removes the effect based on the value of the HasShadow attached property.

A classe LabelShadowEffect aninhada, que cria uma subclasse da classe RoutingEffect, dá suporte à adição e à remoção de efeitos.The nested LabelShadowEffect class, which subclasses the RoutingEffect class, supports effect addition and removal. A classe RoutingEffect representa um efeito independente de plataforma que encapsula um efeito interno, que é geralmente é específico da plataforma.The RoutingEffect class represents a platform-independent effect that wraps an inner effect that is usually platform-specific. Isso simplifica o processo de remoção do efeito, porque não há nenhum acesso de tempo de compilação às informações de tipo para um efeito específico da plataforma.This simplifies the effect removal process, since there is no compile-time access to the type information for a platform-specific effect. O construtor LabelShadowEffect chama o construtor da classe base, passando um parâmetro composto por uma concatenação do nome do grupo de resolução e pela ID exclusiva que foi especificada em cada classe de efeito específica da plataforma.The LabelShadowEffect constructor calls the base class constructor, passing in a parameter consisting of a concatenation of the resolution group name, and the unique ID that was specified on each platform-specific effect class. Isso habilita a adição e a remoção do efeito no método OnHasShadowChanged, da seguinte maneira:This enables effect addition and removal in the OnHasShadowChanged method, as follows:

  • Adição de efeito – uma nova instância do LabelShadowEffect é adicionada à coleção Effects do controle.Effect addition – a new instance of the LabelShadowEffect is added to the control's Effects collection. Isso substitui o uso do método Effect.Resolve para adicionar o efeito.This replaces using the Effect.Resolve method to add the effect.
  • Remoção de efeito – a primeira instância do LabelShadowEffect na coleção Effects do controle é recuperada e removida.Effect removal – the first instance of the LabelShadowEffect in the control's Effects collection is retrieved and removed.

Consumindo o efeitoConsuming the Effect

Cada LabelShadowEffect específico da plataforma pode ser consumido adicionando as propriedades anexadas a um controle Label, conforme demonstrado no exemplo de código XAML a seguir:Each platform-specific LabelShadowEffect can be consumed by adding the attached properties to a Label control, as demonstrated in the following XAML code example:

<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>

O Label equivalente em C# é mostrado no exemplo de código a seguir:The equivalent Label in C# is shown in the following code example:

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));

Definir a propriedade anexada ShadowEffect.HasShadow como true executa o método ShadowEffect.OnHasShadowChanged que adiciona ou remove o LabelShadowEffect ao controle Label.Setting the ShadowEffect.HasShadow attached property to true executes the ShadowEffect.OnHasShadowChanged method that adds or removes the LabelShadowEffect to the Label control. Nos dois exemplos de código, a propriedade anexada ShadowEffect.Color fornece valores de cor específicos da plataforma.In both code examples, the ShadowEffect.Color attached property provides platform-specific color values. Para obter mais informações, confira Classe do dispositivo.For more information, see Device Class.

Além disso, um Button permite que a cor da sombra seja alterada em tempo de execução.In addition, a Button allows the shadow color to be changed at runtime. Quando o usuário clica no Button, a código a seguir altera a cor da sombra definindo a propriedade anexada ShadowEffect.Color:When the Button is clicked, the following code changes the shadow color by setting the ShadowEffect.Color attached property:

ShadowEffect.SetColor (label, Color.Teal);

Consumindo o efeito com um estiloConsuming the Effect with a Style

Os efeitos que podem ser consumidos adicionando propriedades anexadas a um controle também podem ser consumidos por um estilo.Effects that can be consumed by adding attached properties to a control can also be consumed by a style. O exemplo de código XAML abaixo mostra um estilo explícito para o efeito de sombra, que pode ser aplicado a controles Label:The following XAML code example shows an explicit style for the shadow effect, that can be applied to Label controls:

<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>

O Style pode ser aplicado a um Label definindo sua propriedade Style para a instância de Style usando a extensão de marcação StaticResource, conforme demonstrado no exemplo de código a seguir:The Style can be applied to a Label by setting its Style property to the Style instance using the StaticResource markup extension, as demonstrated in the following code example:

<Label Text="Label Shadow Effect" ... Style="{StaticResource ShadowEffectStyle}" />

Para mais informações sobre estilos, confira Estilos.For more information about styles, see Styles.

Criando o efeito em cada plataformaCreating the Effect on each Platform

As seções a seguir abordam a implementação da classe LabelShadowEffect específica da plataforma.The following sections discuss the platform-specific implementation of the LabelShadowEffect class.

Projeto do iOSiOS Project

O exemplo de código a seguir mostra a implementação de LabelShadowEffect para o projeto do iOS:The following code example shows the LabelShadowEffect implementation for the iOS project:

[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.CornerRadius = (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));
        }
    }

O método OnAttached chama métodos que recuperam os valores de propriedade anexada usando os getters ShadowEffect e que definem as propriedades de Control.Layer com os valores da propriedade para criar a sombra.The OnAttached method calls methods that retrieve the attached property values using the ShadowEffect getters, and which set Control.Layer properties to the property values to create the shadow. Essa funcionalidade é encapsulada em um bloco try/catch caso o controle a que o efeito está anexado não tenha as propriedades de Control.Layer.This functionality is wrapped in a try/catch block in case the control that the effect is attached to does not have the Control.Layer properties. Nenhuma implementação é fornecida pelo método OnDetached porque nenhuma limpeza é necessária.No implementation is provided by the OnDetached method because no cleanup is necessary.

Respondendo a alterações de propriedadeResponding to Property Changes

Se qualquer um dos valores da propriedade anexada ShadowEffect for alterado em tempo de execução, o efeito precisará responder exibindo as alterações.If any of the ShadowEffect attached property values change at runtime, the effect needs to respond by displaying the changes. Uma versão de substituição do método OnElementPropertyChanged, na classe de efeito específica da plataforma, é o lugar para responder a alterações de propriedade vinculáveis, conforme demonstrado no código de exemplo a seguir:An overridden version of the OnElementPropertyChanged method, in the platform-specific effect class, is the place to respond to bindable property changes, as demonstrated in the following code example:

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 ();
    }
  }
  ...
}

O método OnElementPropertyChanged atualiza o raio, a cor ou o deslocamento da sombra, desde que o valor da propriedade anexada ShadowEffect tenha sido alterado.The OnElementPropertyChanged method updates the radius, color, or offset of the shadow, provided that the appropriate ShadowEffect attached property value has changed. Uma verificação da propriedade alterada sempre deve ser feita, pois essa substituição pode ser chamada várias vezes.A check for the property that's changed should always be made, as this override can be called many times.

Projeto do AndroidAndroid Project

O exemplo de código a seguir mostra a implementação de LabelShadowEffect para o projeto do Android:The following code example shows the LabelShadowEffect implementation for the Android project:

[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);
        }
    }

O método OnAttached chama métodos que recuperam os valores de propriedade anexada usando os getters ShadowEffect e chama um método que chama o método TextView.SetShadowLayer para criar uma sombra usando os valores da propriedade.The OnAttached method calls methods that retrieve the attached property values using the ShadowEffect getters, and calls a method that calls the TextView.SetShadowLayer method to create a shadow using the property values. Essa funcionalidade é encapsulada em um bloco try/catch caso o controle a que o efeito está anexado não tenha as propriedades de Control.Layer.This functionality is wrapped in a try/catch block in case the control that the effect is attached to does not have the Control.Layer properties. Nenhuma implementação é fornecida pelo método OnDetached porque nenhuma limpeza é necessária.No implementation is provided by the OnDetached method because no cleanup is necessary.

Respondendo a alterações de propriedadeResponding to Property Changes

Se qualquer um dos valores da propriedade anexada ShadowEffect for alterado em tempo de execução, o efeito precisará responder exibindo as alterações.If any of the ShadowEffect attached property values change at runtime, the effect needs to respond by displaying the changes. Uma versão de substituição do método OnElementPropertyChanged, na classe de efeito específica da plataforma, é o lugar para responder a alterações de propriedade vinculáveis, conforme demonstrado no código de exemplo a seguir:An overridden version of the OnElementPropertyChanged method, in the platform-specific effect class, is the place to respond to bindable property changes, as demonstrated in the following code example:

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 ();
    }
  }
  ...
}

O método OnElementPropertyChanged atualiza o raio, a cor ou o deslocamento da sombra, desde que o valor da propriedade anexada ShadowEffect tenha sido alterado.The OnElementPropertyChanged method updates the radius, color, or offset of the shadow, provided that the appropriate ShadowEffect attached property value has changed. Uma verificação da propriedade alterada sempre deve ser feita, pois essa substituição pode ser chamada várias vezes.A check for the property that's changed should always be made, as this override can be called many times.

Projeto da Plataforma Universal do WindowsUniversal Windows Platform Project

O exemplo de código a seguir mostra a implementação de LabelShadowEffect para o projeto da UWP (Plataforma Universal do Windows):The following code example shows the LabelShadowEffect implementation for the Universal Windows Platform (UWP) project:

[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);
        }
    }
}

A Plataforma Universal do Windows não fornece um efeito de sombra, de forma que a implementação de LabelShadowEffect nas duas plataformas simula o efeito adicionando um segundo deslocamento Label atrás do Label principal.The Universal Windows Platform doesn't provide a shadow effect, and so the LabelShadowEffect implementation on both platforms simulates one by adding a second offset Label behind the primary Label. O método OnAttached cria o novo Label e define algumas propriedades de layout no Label.The OnAttached method creates the new Label and sets some layout properties on the Label. Em seguida, ele chama métodos que recuperam os valores da propriedade anexada usando os getters ShadowEffect e cria a sombra definindo as propriedades TextColor, TranslationX e TranslationY para controlar a cor e a localização do Label.It then calls methods that retrieve the attached property values using the ShadowEffect getters, and creates the shadow by setting the TextColor, TranslationX, and TranslationY properties to control the color and location of the Label. Em seguida, o shadowLabel é inserido deslocado atrás do Label principal.The shadowLabel is then inserted offset behind the primary Label. Essa funcionalidade é encapsulada em um bloco try/catch caso o controle a que o efeito está anexado não tenha as propriedades de Control.Layer.This functionality is wrapped in a try/catch block in case the control that the effect is attached to does not have the Control.Layer properties. Nenhuma implementação é fornecida pelo método OnDetached porque nenhuma limpeza é necessária.No implementation is provided by the OnDetached method because no cleanup is necessary.

Respondendo a alterações de propriedadeResponding to Property Changes

Se qualquer um dos valores da propriedade anexada ShadowEffect for alterado em tempo de execução, o efeito precisará responder exibindo as alterações.If any of the ShadowEffect attached property values change at runtime, the effect needs to respond by displaying the changes. Uma versão de substituição do método OnElementPropertyChanged, na classe de efeito específica da plataforma, é o lugar para responder a alterações de propriedade vinculáveis, conforme demonstrado no código de exemplo a seguir:An overridden version of the OnElementPropertyChanged method, in the platform-specific effect class, is the place to respond to bindable property changes, as demonstrated in the following code example:

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 ();
    }
  }
  ...
}

O método OnElementPropertyChanged atualiza a cor ou o deslocamento da sombra, desde que o valor da propriedade anexada ShadowEffect tenha sido alterado.The OnElementPropertyChanged method updates the color or offset of the shadow, provided that the appropriate ShadowEffect attached property value has changed. Uma verificação da propriedade alterada sempre deve ser feita, pois essa substituição pode ser chamada várias vezes.A check for the property that's changed should always be made, as this override can be called many times.

ResumoSummary

Este artigo demonstrou o uso de propriedades anexadas para passar parâmetros para um efeito e a alteração de um parâmetro em tempo de execução.This article has demonstrated using attached properties to pass parameters to an effect, and changing a parameter at runtime. Propriedades anexadas podem ser usadas para definir parâmetros de efeito que respondem a alterações de propriedade de tempo de execução.Attached properties can be used to define effect parameters that respond to runtime property changes.