공용 언어 런타임 속성으로 효과 매개 변수 전달Passing Effect Parameters as Common Language Runtime Properties

샘플 다운로드 샘플 다운로드Download Sample Download the sample

CLR(공용 언어 런타임) 속성은 런타임 속성 변경 내용에 응답하지 않는 효과 매개 변수를 정의하는 데 사용할 수 있습니다. 이 문서에서는 CLR 속성을 사용하여 매개 변수를 효과에 전달하는 방법을 설명합니다.Common Language Runtime (CLR) properties can be used to define effect parameters that don't respond to runtime property changes. This article demonstrates using CLR properties to pass parameters to an effect.

런타임 속성 변경 내용에 응답하지 않는 효과 매개 변수를 만드는 프로세스는 다음과 같습니다.The process for creating effect parameters that don't respond to runtime property changes is as follows:

  1. RoutingEffect 클래스를 서브클래스하는 public 클래스를 만듭니다.Create a public class that subclasses the RoutingEffect class. RoutingEffect 클래스는 일반적으로 플랫폼에 따라 내부 효과를 래핑하는 플랫폼 독립적인 효과를 나타냅니다.The RoutingEffect class represents a platform-independent effect that wraps an inner effect that is usually platform-specific.
  2. 기본 클래스 생성자를 호출하여 해상도 그룹 이름의 연결과 각 플랫폼별 효과 클래스에 지정된 고유 ID를 전달하는 생성자를 만듭니다.Create a constructor that calls 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.
  3. 효과에 전달될 각 매개 변수에 대한 클래스에 속성을 추가합니다.Add properties to the class for each parameter to be passed to the effect.

그런 다음, 효과를 인스턴스화할 때 각 속성에 대한 값을 지정하여 매개 변수를 효과에 전달할 수 있습니다.Parameters can then be passed to the effect by specifying values for each property when instantiating the effect.

샘플 애플리케이션은 Label 컨트롤에서 표시되는 텍스트에 그림자를 추가하는 ShadowEffect를 설명합니다.The sample application demonstrates a ShadowEffect that adds a shadow to the text displayed by a Label control. 다음 다이어그램은 샘플 애플리케이션에서 각 프로젝트의 책임과 이들 간의 관계를 보여줍니다.The following diagram illustrates the responsibilities of each project in the sample application, along with the relationships between them:

HomePageLabel 컨트롤은 각 플랫폼별 프로젝트에서 LabelShadowEffect로 사용자 지정됩니다.A Label control on the HomePage is customized by the LabelShadowEffect in each platform-specific project. 매개 변수는 ShadowEffect 클래스의 속성을 통해 각 LabelShadowEffect에 전달됩니다.Parameters are passed to each LabelShadowEffect through properties in the ShadowEffect class. LabelShadowEffect 클래스는 각 플랫폼에 대한 PlatformEffect 클래스에서 파생됩니다.Each LabelShadowEffect class derives from the PlatformEffect class for each platform. 그러면 다음 스크린샷에 표시된 대로 Label 컨트롤에서 표시되는 텍스트에 그림자가 추가됩니다.This results in a shadow being added to the text displayed by the Label control, as shown in the following screenshots:

효과 매개 변수 만들기Creating Effect Parameters

다음 코드 예제에서 설명한 것처럼 효과 매개 변수를 표현하도록 RoutingEffect 클래스를 서브클래스하는 public 클래스를 만들어야 합니다.A public class that subclasses the RoutingEffect class should be created to represent effect parameters, as demonstrated in the following code example:

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

ShadowEffect에는 각 플랫폼별 LabelShadowEffect에 전달할 매개 변수를 나타내는 네 가지 속성이 포함되어 있습니다.The ShadowEffect contains four properties that represent parameters to be passed to each platform-specific LabelShadowEffect. 클래스 생성자는 기본 클래스 생성자를 호출하여 해상도 그룹 이름의 연결과 각 플랫폼별 효과 클래스에 지정된 고유 ID로 이루어진 매개 변수를 전달합니다.The class 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. 따라서 ShadowEffect가 인스턴스화될 때 MyCompany.LabelShadowEffect의 새 인스턴스가 컨트롤의 Effects 컬렉션에 추가됩니다.Therefore, a new instance of the MyCompany.LabelShadowEffect will be added to a control's Effects collection when a ShadowEffect is instantiated.

효과 사용Consuming the Effect

다음 XAML 코드 예제는 ShadowEffect가 연결된 Label 컨트롤을 보여줍니다.The following XAML code example shows a Label control to which the ShadowEffect is attached:

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

해당하는 C#의 Label가 다음 코드 예제에 나와 있습니다.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;
}

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

두 코드 예제에서 ShadowEffect 클래스의 인스턴스는 컨트롤의 Effects 컬렉션에 추가되기 전에 각 속성에 대해 지정되는 값을 사용하여 인스턴스화됩니다.In both code examples, an instance of the ShadowEffect class is instantiated with values being specified for each property, before being added to the control's Effects collection. ShadowEffect.Color 속성은 플랫폼별 색 값을 사용합니다.Note that the ShadowEffect.Color property uses platform-specific color values. 자세한 내용은 디바이스 클래스를 참조하세요.For more information, see Device Class.

각 플랫폼의 효과 만들기Creating the Effect on each Platform

다음 섹션에서는 LabelShadowEffect 클래스의 플랫폼별 구현을 설명합니다.The following sections discuss the platform-specific implementation of the LabelShadowEffect class.

iOS 프로젝트iOS Project

다음 코드 예제는 iOS 프로젝트에 대한 LabelShadowEffect 구현을 보여줍니다.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 {
                var effect = (ShadowEffect)Element.Effects.FirstOrDefault (e => e is ShadowEffect);
                if (effect != null) {
                    Control.Layer.CornerRadius = 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 ()
        {
        }
    }
}

OnAttached 메서드는 ShadowEffect 인스턴스를 검색하고, Control.Layer 속성을 그림자를 만들도록 지정된 속성 값으로 설정합니다.The OnAttached method retrieves the ShadowEffect instance, and sets Control.Layer properties to the specified property values to create the shadow. 이 기능은 효과가 연결된 컨트롤에 Control.Layer 속성이 없는 경우 try/catch 블록에 래핑됩니다.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. 정리가 필요하지 않으므로 OnDetached 메서드에 의한 구현은 제공되지 않습니다.No implementation is provided by the OnDetached method because no cleanup is necessary.

Android 프로젝트Android Project

다음 코드 예제는 Android 프로젝트에 대한 LabelShadowEffect 구현을 보여줍니다.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
    {
        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 ()
        {
        }
    }
}

OnAttached 메서드는 ShadowEffect 인스턴스를 검색하고, 지정된 속성 값을 사용하여 그림자를 만들도록 TextView.SetShadowLayer 메서드를 호출합니다.The OnAttached method retrieves the ShadowEffect instance, and calls the TextView.SetShadowLayer method to create a shadow using the specified property values. 이 기능은 효과가 연결된 컨트롤에 Control.Layer 속성이 없는 경우 try/catch 블록에 래핑됩니다.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. 정리가 필요하지 않으므로 OnDetached 메서드에 의한 구현은 제공되지 않습니다.No implementation is provided by the OnDetached method because no cleanup is necessary.

유니버설 Windows 플랫폼 프로젝트Universal Windows Platform Project

다음 코드 예제는 UWP(유니버설 Windows 플랫폼) 프로젝트에 대한 LabelShadowEffect 구현을 보여줍니다.The following code example shows the LabelShadowEffect implementation for the Universal Windows Platform (UWP) project:

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

유니버설 Windows 플랫폼은 그림자 효과를 제공하지 않으므로 두 가지 플랫폼의 LabelShadowEffect 구현은 기본 Label 뒤에 두 번째 오프셋 Label을 추가하여 시뮬레이션합니다.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. OnAttached 메서드는 ShadowEffect 인스턴스를 검색하고, 새 Label을 만든 후, 일부 레이아웃 속성을 Label로 설정합니다.The OnAttached method retrieves the ShadowEffect instance, creates the new Label, and sets some layout properties on the Label. 그런 다음, TextColor, TranslationXTranslationY 속성을 설정하여 그림자를 생성하여 Label의 위치와 색을 제어합니다.It then creates the shadow by setting the TextColor, TranslationX, and TranslationY properties to control the color and location of the Label. 그런 다음, shadowLabel이 기본 Label 뒤에 삽입됩니다.The shadowLabel is then inserted offset behind the primary Label. 이 기능은 효과가 연결된 컨트롤에 Control.Layer 속성이 없는 경우 try/catch 블록에 래핑됩니다.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. 정리가 필요하지 않으므로 OnDetached 메서드에 의한 구현은 제공되지 않습니다.No implementation is provided by the OnDetached method because no cleanup is necessary.

요약Summary

이 문서에서는 CLR 속성을 사용하여 매개 변수를 효과에 전달하는 방법을 설명했습니다.This article has demonstrated using CLR properties to pass parameters to an effect. CLR 속성은 런타임 속성 변경 내용에 응답하지 않는 효과 매개 변수를 정의하는 데 사용할 수 있습니다.CLR properties can be used to define effect parameters that don't respond to runtime property changes.