エフェクトの作成

Download Sampleサンプルのダウンロード

エフェクトにより、コントロールのカスタマイズが簡略化されます。 この記事では、入力コントロールがフォーカスを取得したときにコントロールの背景色を変更するエフェクトの作成方法を示します。"

各プラットフォーム固有のプロジェクトで効果を作成するプロセスは次のとおりです。

  1. PlatformEffect クラスのサブクラスを作成します。
  2. OnAttached メソッドをオーバーライドし、コントロールをカスタマイズするロジックを記述します。
  3. OnDetached メソッドをオーバーライドし、コントロールのカスタマイズをクリーンアップするロジックを記述します (必要な場合)。
  4. ResolutionGroupName 属性をエフェクトクラスに追加します。 この属性により、会社全体の名前空間が設定され、同じ名前を持つその他のエフェクトとの競合が防止されます。 この属性はプロジェクトごとに 1 回のみ 適用できることに注意してください。
  5. ExportEffect 属性をエフェクトクラスに追加します。 この属性によって、Xamarin.Forms で使用される一意の ID とコントロールに適用する前にエフェクトを検索するためのグループ名付きでエフェクトが登録されます。 この属性では、エフェクトの種類名と、コントロールに適用する前にエフェクトを検索するために使用される一意の文字列という 2 つのパラメーターが使用されます。

その後、適切なコントロールにアタッチすることで、エフェクトを使用できます。

Note

各プラットフォーム プロジェクトにエフェクトを提供するかどうかは任意です。 エフェクトが登録されていない場合にそれを使用しようとすると、何も実行しない null 以外の値が返されます。

サンプル アプリケーションでは、コントロールがフォーカスを取得したときに背景色を変更する FocusEffect を示します。 次の図に、サンプル アプリケーション内の各プロジェクトの役割と、それらの関係を示します。

Focus Effect Project Responsibilities

HomePage 上の Entry コントロールが、各プラットフォーム固有のプロジェクト内の FocusEffect クラスによってカスタマイズされます。 各プラットフォームの PlatformEffect クラスから、各 FocusEffect クラスが派生します。 この結果、次のスクリーンショットに示すように、プラットフォーム固有の背景色を使用して Entry コントロールがレンダリングされ、フォーカスを取得するとその色が変更されます。

Focus Effect on each Platform, control focusedFocus Effect on each Platform, control unfocused

各プラットフォームでのエフェクトの作成

次のセクションで、FocusEffect クラスのプラットフォーム固有の実装について説明します。

iOS プロジェクト

iOS プロジェクト用の FocusEffect の実装を次のコード例に示します。

using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

[assembly:ResolutionGroupName ("MyCompany")]
[assembly:ExportEffect (typeof(EffectsDemo.iOS.FocusEffect), nameof(EffectsDemo.iOS.FocusEffect))]
namespace EffectsDemo.iOS
{
    public class FocusEffect : PlatformEffect
    {
        UIColor backgroundColor;

        protected override void OnAttached ()
        {
            try {
                Control.BackgroundColor = backgroundColor = UIColor.FromRGB (204, 153, 255);
            } catch (Exception ex) {
                Console.WriteLine ("Cannot set property on attached control. Error: ", ex.Message);
            }
        }

        protected override void OnDetached ()
        {
        }

        protected override void OnElementPropertyChanged (PropertyChangedEventArgs args)
        {
            base.OnElementPropertyChanged (args);

            try {
                if (args.PropertyName == "IsFocused") {
                    if (Control.BackgroundColor == backgroundColor) {
                        Control.BackgroundColor = UIColor.White;
                    } else {
                        Control.BackgroundColor = backgroundColor;
                    }
                }
            } catch (Exception ex) {
                Console.WriteLine ("Cannot set property on attached control. Error: ", ex.Message);
            }
        }
    }
}

OnAttached メソッドでは、UIColor.FromRGB メソッドを使用してコントロールを紫色にすると共にその色をフィールドに格納する BackgroundColor プロパティ が設定されます。 エフェクトがアタッチされているコントロールに BackgroundColor プロパティがない場合に備えて、この機能が try/catch ブロック内にラップされます。 クリーンアップする必要がないので、OnDetached メソッドによる実装は提供されません。

OnElementPropertyChanged オーバーライドで、Xamarin.Forms コントロールのバインド可能プロパティの変更に応答します。 IsFocused プロパティが変更されたときに、コントロールがフォーカスを取得している場合は、コントロールの BackgroundColor プロパティが白に変更され、それ以外の場合は明るい紫に変更されます。 エフェクトがアタッチされているコントロールに BackgroundColor プロパティがない場合に備えて、この機能が try/catch ブロック内にラップされます。

Android プロジェクト

Android プロジェクト用の FocusEffect の実装を次のコード例に示します。

using System;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly: ResolutionGroupName("MyCompany")]
[assembly: ExportEffect(typeof(EffectsDemo.Droid.FocusEffect), nameof(EffectsDemo.Droid.FocusEffect))]
namespace EffectsDemo.Droid
{
    public class FocusEffect : PlatformEffect
    {
        Android.Graphics.Color originalBackgroundColor = new Android.Graphics.Color(0, 0, 0, 0);
        Android.Graphics.Color backgroundColor;

        protected override void OnAttached()
        {
            try
            {
                backgroundColor = Android.Graphics.Color.LightGreen;
                Control.SetBackgroundColor(backgroundColor);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Cannot set property on attached control. Error: ", ex.Message);
            }
        }

        protected override void OnDetached()
        {
        }

        protected override void OnElementPropertyChanged(System.ComponentModel.PropertyChangedEventArgs args)
        {
            base.OnElementPropertyChanged(args);
            try
            {
                if (args.PropertyName == "IsFocused")
                {
                    if (((Android.Graphics.Drawables.ColorDrawable)Control.Background).Color == backgroundColor)
                    {
                        Control.SetBackgroundColor(originalBackgroundColor);
                    }
                    else
                    {
                        Control.SetBackgroundColor(backgroundColor);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Cannot set property on attached control. Error: ", ex.Message);
            }
        }
    }
}

OnAttached メソッドでは、SetBackgroundColor メソッドを呼び出して、コントロールの背景色を明るい緑にすると共にその色をフィールドに格納します。 エフェクトがアタッチされているコントロールに SetBackgroundColor プロパティがない場合に備えて、この機能が try/catch ブロック内にラップされます。 クリーンアップする必要がないので、OnDetached メソッドによる実装は提供されません。

OnElementPropertyChanged オーバーライドで、Xamarin.Forms コントロールのバインド可能プロパティの変更に応答します。 IsFocused プロパティが変更されたときに、コントロールがフォーカスを取得している場合は、コントロールの背景色が白に変更され、それ以外の場合は明るい緑に変更されます。 エフェクトがアタッチされているコントロールに BackgroundColor プロパティがない場合に備えて、この機能が try/catch ブロック内にラップされます。

ユニバーサル Windows プラットフォーム プロジェクト

ユニバーサル Windows プラットフォーム (UWP) プロジェクト用の FocusEffect の実装を次のコード例に示します。

using Xamarin.Forms;
using Xamarin.Forms.Platform.UWP;

[assembly: ResolutionGroupName("MyCompany")]
[assembly: ExportEffect(typeof(EffectsDemo.UWP.FocusEffect), nameof(EffectsDemo.UWP.FocusEffect))]
namespace EffectsDemo.UWP
{
    public class FocusEffect : PlatformEffect
    {
        protected override void OnAttached()
        {
            try
            {
                (Control as Windows.UI.Xaml.Controls.Control).Background = new SolidColorBrush(Colors.Cyan);
                (Control as FormsTextBox).BackgroundFocusBrush = new SolidColorBrush(Colors.White);
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Cannot set property on attached control. Error: ", ex.Message);
            }
        }

        protected override void OnDetached()
        {
        }
    }
}

OnAttached メソッドでは、コントロールの Background プロパティをシアンに設定し、BackgroundFocusBrush プロパティを白に設定します。 エフェクトがアタッチされているコントロールにこれらのプロパティがない場合に備えて、この機能が try/catch ブロック内にラップされます。 クリーンアップする必要がないので、OnDetached メソッドによる実装は提供されません。

エフェクトの使用

Xamarin.Forms .NET Standard ライブラリまたは共有ライブラリ プロジェクトからエフェクトを使用するプロセスは次のとおりです。

  1. エフェクトによってカスタマイズされるコントロールを宣言します。
  2. コントロールの Effects コレクションに追加することによって、エフェクトをコントロールにアタッチします。

Note

エフェクト インスタンスは単一のコントロールにのみアタッチできます。 このため、2 つのコントロールで使用するには、エフェクトを 2 回解決する必要があります。

XAML でのエフェクトの使用

FocusEffect がアタッチされている Entry コントロールを、次の XAML コード例に示します。

<Entry Text="Effect attached to an Entry" ...>
    <Entry.Effects>
        <local:FocusEffect />
    </Entry.Effects>
    ...
</Entry>

.NET Standard ライブラリ内の FocusEffect クラスでは、XAML での効果の使用がサポートされます。これを次のコード例に示します。

public class FocusEffect : RoutingEffect
{
    public FocusEffect () : base ($"MyCompany.{nameof(FocusEffect)}")
    {
    }
}

FocusEffect クラスで RoutingEffect クラスがサブクラス化されます。これは、通常はプラットフォーム固有である内部効果をラップするプラットフォームに依存しない効果を表します。 FocusEffect クラスで基底クラス コンストラクターが呼び出され、解決グループ名 (効果クラスの ResolutionGroupName 属性を使用して指定されます) と効果クラスの ExportEffect 属性を使用して指定された一意の ID の連結を構成するパラメーターが渡されます。 このため、実行時に Entry が初期化されるときに、MyCompany.FocusEffect の新しいインスタンスがコントロールの Effects コレクションに追加されます。

ビヘイビアーを使用するか、アタッチされるプロパティを使用して、効果をアタッチすることもできます。 ビヘイビアーを使用してコントロールに効果をアタッチする方法の詳細については、「Reusable EffectBehavior」(再利用可能な EffectBehavior) を参照してください。 アタッチされるプロパティを使用してコントロールに効果をアタッチする方法の詳細については、「Passing Parameters to an Effect」(効果にパラメーターを渡す) を参照してください。

C# でのエフェクトの使用

C# での同等の Entry を次のコード例に示します。

var entry = new Entry {
  Text = "Effect attached to an Entry",
  ...
};

次のコード例に示すように、効果をコントロールの Effects コレクションに追加することで、FocusEffectEntry インスタンスにアタッチされます。

public HomePageCS ()
{
  ...
  entry.Effects.Add (Effect.Resolve ($"MyCompany.{nameof(FocusEffect)}"));
  ...
}

Effect.Resolve によって、指定された名前用の Effect が返されます。これは解決グループ名 (効果クラスの ResolutionGroupName 属性を使用して指定されます) と効果クラスの ExportEffect 属性を使用して指定された一意の ID の連結を構成するパラメーターです。 プラットフォームでエフェクトが提供されない場合、Effect.Resolve メソッドでは、null 以外の値が返されます。

まとめ

この記事では、Entry コントロールがフォーカスを取得したときにコントロールの背景色を変更するエフェクトの作成方法を示しました。