Partager via


Passer des paramètres d’effet en tant que propriétés CLR (Common Language Runtime)

Les propriétés CLR (Common Language Runtime) permettent de définir des paramètres d’effet qui ne répondent pas aux changements apportés aux propriétés au moment de l’exécution. Cet article montre comment utiliser des propriétés CLR pour passer des paramètres à un effet.

Pour créer des paramètres d’effet qui ne répondent pas aux changements apportés aux propriétés au moment de l’exécution, suivez ces étapes :

  1. Créez une classe public qui sous-classe la classe RoutingEffect. La classe RoutingEffect représente un effet indépendant de la plateforme qui wrappe un effet interne généralement propre à une plateforme.
  2. Créez un constructeur qui appelle le constructeur de classe de base, en passant une concaténation du nom du groupe de résolution, et l’ID unique qui a été spécifié sur la classe d’effet propre à chaque plateforme.
  3. Ajoutez des propriétés à la classe pour chaque paramètre à passer à l’effet.

Les paramètres peuvent ensuite être passés à l’effet en spécifiant des valeurs pour chaque propriété lors de l’instanciation de l’effet.

L’exemple d’application montre un ShadowEffect qui ajoute une ombre au texte affiché par un contrôle Label. Le diagramme suivant illustre les responsabilités de chaque projet dans l’exemple d’application ainsi que les relations qu’ils entretiennent les uns avec les autres :

Responsabilités de projet ShadowEffect

Un contrôle Label sur HomePage est personnalisé par LabelShadowEffect dans chaque projet propre à la plateforme. Les paramètres sont passés à chaque LabelShadowEffect par le biais des propriétés dans la classe ShadowEffect. Chaque classe LabelShadowEffect dérive de la classe PlatformEffect pour chaque plateforme. Il en résulte l’ajout d’une ombre au texte affiché par le contrôle Label, comme illustré dans les captures d’écran suivantes :

Effet d’ombre sur chaque plateforme

Création de paramètres d’effet

Une classe public sous-classant la classe RoutingEffect doit être créée pour représenter les paramètres d’effet, comme illustré dans l’exemple de code suivant :

public class ShadowEffect : RoutingEffect
{
  public float Radius { get; set; }

  public Color Color { get; set; }

  public float DistanceX { get; set; }

  public float DistanceY { get; set; }

  public ShadowEffect () : base ("MyCompany.LabelShadowEffect")
  {            
  }
}

LabelShadowEffect contient quatre propriétés qui représentent les paramètres à passer à chaque ShadowEffect propre à la plateforme. Le constructeur de classe appelle le constructeur de classe de base, en passant un paramètre constitué d’une concaténation du nom du groupe de résolution, et l’ID unique qui a été spécifié sur la classe d’effet propre à chaque plateforme. Par conséquent, une nouvelle instance de MyCompany.LabelShadowEffect sera ajoutée à la collection Effects d’un contrôle au moment de l’instanciation de ShadowEffect.

Consommation de l’effet

L’exemple de code XAML suivant montre un contrôle Label auquel est joint ShadowEffect :

<Label Text="Label Shadow Effect" ...>
  <Label.Effects>
    <local:ShadowEffect Radius="5" DistanceX="5" 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>
    </local:ShadowEffect>
  </Label.Effects>
</Label>

Le contrôle Label équivalent en C# est présenté dans l’exemple de code suivant :

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

label.Effects.Add (new ShadowEffect {
  Radius = 5,
  Color = color,
  DistanceX = 5,
  DistanceY = 5
});

Dans les deux exemples de code, une instance de la classe ShadowEffect est instanciée avec des valeurs spécifiées pour chaque propriété, avant d’être ajoutée à la collection Effects du contrôle. Notez que la propriété ShadowEffect.Color utilise des valeurs de couleur différentes pour chaque plateforme. Pour plus d’informations, consultez l’article sur la classe Device.

Création de l’effet sur chaque plateforme

Les sections suivantes décrivent l’implémentation de la classe LabelShadowEffect pour chaque plateforme.

Projet iOS

L’exemple de code suivant illustre l’implémentation de LabelShadowEffect pour le projet iOS :

[assembly:ResolutionGroupName ("MyCompany")]
[assembly:ExportEffect (typeof(LabelShadowEffect), "LabelShadowEffect")]
namespace EffectsDemo.iOS
{
    public class LabelShadowEffect : PlatformEffect
    {
        protected override void OnAttached ()
        {
            try {
                var effect = (ShadowEffect)Element.Effects.FirstOrDefault (e => e is ShadowEffect);
                if (effect != null) {
                    Control.Layer.ShadowRadius = effect.Radius;
                    Control.Layer.ShadowColor = effect.Color.ToCGColor ();
                    Control.Layer.ShadowOffset = new CGSize (effect.DistanceX, effect.DistanceY);
                    Control.Layer.ShadowOpacity = 1.0f;
                }
            } catch (Exception ex) {
                Console.WriteLine ("Cannot set property on attached control. Error: ", ex.Message);
            }
        }

        protected override void OnDetached ()
        {
        }
    }
}

La méthode OnAttached récupère l’instance ShadowEffect et définit les propriétés Control.Layer sur les valeurs de propriété spécifiées pour créer l’ombre. Cette fonctionnalité est wrappée dans un bloc try/catch au cas où le contrôle auquel l’effet est joint n’a pas les propriétés Control.Layer. Aucune implémentation n’est fournie par la méthode OnDetached, car aucun nettoyage n’est nécessaire.

Projet Android

L’exemple de code suivant illustre l’implémentation de LabelShadowEffect pour le projet Android :

[assembly:ResolutionGroupName ("MyCompany")]
[assembly:ExportEffect (typeof(LabelShadowEffect), "LabelShadowEffect")]
namespace EffectsDemo.Droid
{
    public class LabelShadowEffect : PlatformEffect
    {
        protected override void OnAttached ()
        {
            try {
                var control = Control as Android.Widget.TextView;
                var effect = (ShadowEffect)Element.Effects.FirstOrDefault (e => e is ShadowEffect);
                if (effect != null) {
                    float radius = effect.Radius;
                    float distanceX = effect.DistanceX;
                    float distanceY = effect.DistanceY;
                    Android.Graphics.Color color = effect.Color.ToAndroid ();
                    control.SetShadowLayer (radius, distanceX, distanceY, color);
                }
            } catch (Exception ex) {
                Console.WriteLine ("Cannot set property on attached control. Error: ", ex.Message);
            }
        }

        protected override void OnDetached ()
        {
        }
    }
}

La méthode OnAttached récupère l’instance ShadowEffect et appelle la méthode TextView.SetShadowLayer pour créer une ombre en utilisant les valeurs de propriété spécifiées. Cette fonctionnalité est wrappée dans un bloc try/catch au cas où le contrôle auquel l’effet est joint n’a pas les propriétés Control.Layer. Aucune implémentation n’est fournie par la méthode OnDetached, car aucun nettoyage n’est nécessaire.

Projet de plateforme Windows universelle

L’exemple de code suivant montre l’implémentation de LabelShadowEffect pour le projet de plateforme Windows universelle (UWP) :

[assembly: ResolutionGroupName ("Xamarin")]
[assembly: ExportEffect (typeof(LabelShadowEffect), "LabelShadowEffect")]
namespace EffectsDemo.UWP
{
    public class LabelShadowEffect : PlatformEffect
    {
        bool shadowAdded = false;

        protected override void OnAttached ()
        {
            try {
                if (!shadowAdded) {
                    var effect = (ShadowEffect)Element.Effects.FirstOrDefault (e => e is ShadowEffect);
                    if (effect != null) {
                        var textBlock = Control as Windows.UI.Xaml.Controls.TextBlock;
                        var shadowLabel = new Label ();
                        shadowLabel.Text = textBlock.Text;
                        shadowLabel.FontAttributes = FontAttributes.Bold;
                        shadowLabel.HorizontalOptions = LayoutOptions.Center;
                        shadowLabel.VerticalOptions = LayoutOptions.CenterAndExpand;
                        shadowLabel.TextColor = effect.Color;
                        shadowLabel.TranslationX = effect.DistanceX;
                        shadowLabel.TranslationY = effect.DistanceY;

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

La plateforme Windows universelle ne fournissant pas d’effet d’ombre, l’implémentation de LabelShadowEffect sur les deux plateformes en simule un en ajoutant un deuxième décalage Label derrière le contrôle Label principal. La méthode OnAttached récupère l’instance ShadowEffect, crée le nouveau contrôle Label et définit certaines propriétés de disposition sur Label. Elle crée ensuite l’ombre en définissant les propriétés TextColor, TranslationX et TranslationY qui contrôlent la couleur et l’emplacement de Label. Le contrôle shadowLabel est alors inséré en décalage derrière le contrôle Label principal. Cette fonctionnalité est wrappée dans un bloc try/catch au cas où le contrôle auquel l’effet est joint n’a pas les propriétés Control.Layer. Aucune implémentation n’est fournie par la méthode OnDetached, car aucun nettoyage n’est nécessaire.

Résumé

Cet article a montré comment utiliser des propriétés CLR pour passer des paramètres à un effet. Les propriétés CLR permettent de définir des paramètres d’effet qui ne répondent pas aux changements apportés aux propriétés au moment de l’exécution.