動作

Browse sample. サンプルを参照する

.NET Multi-Platform App UI (.NET MAUI) 動作を使うと、ユーザー インターフェイス コントロールをサブクラス化することなく、それらに機能を追加できます。 代わりに、その機能はビヘイビアー クラスで実装され、それがコントロール自体の一部であるかのようにコントロールにアタッチされます。

ビヘイビアーを使うと、通常はコードビハインドとして記述する必要があるコードを実装できます。これは、コントロールに簡潔にアタッチされ、複数のアプリケーション全体で再利用できるようにパッケージ化される方法で、コントロールの API と直接対話しているためです。 これらを使用して、次のようなさまざまな機能をコントロールに提供できます。

  • Entry にメール検証機能を追加する。
  • タップ ジェスチャ認識エンジンを使用して評価コントロールを作成する。
  • アニメーションを制御する。

.NET MAUI では、次の 3 種類の動作がサポートされています。

  • アタッチされたビヘイビアーは、1 つ以上のアタッチされたプロパティを含む static クラスです。 添付ビヘイビアーの詳細については、「添付ビヘイビアー」をご覧ください。
  • .NET MAUI ビヘイビアーは、Behavior または Behavior<T> から派生したクラスで、T は、動作が適用されるコントロールの型です。 詳細については、「.NET MAUI ビヘイビアー」をご覧ください。
  • プラットフォームの動作は、PlatformBehavior<TView> または PlatformBehavior<TView,TPlatformView> クラスから派生するクラスです。 これらの動作は、ネイティブ コントロールの任意の条件とイベントに応答できます。 詳細については、「プラットフォーム動作」をご覧ください。

添付ビヘイビアー

アタッチされたビヘイビアーは、1 つ以上のプロパティがアタッチされた静的クラスです。 添付プロパティは、特殊な種類のバインド可能プロパティです。 1 つのクラスで定義される一方で他のオブジェクトにアタッチされ、XAML 内でピリオドで区切られたクラスとプロパティ名が含まれる属性として認識されます。 添付プロパティの詳細については、「添付プロパティ」をご覧ください。

添付プロパティでは、プロパティがコントロールに設定されたときなど、プロパティの値が変更されたときに実行される propertyChanged のデリゲートを定義できます。 propertyChanged のデリゲートが実行されると、アタッチされているコントロールへの参照と、プロパティの古い値と新しい値を含むパラメーターが渡されます。 このデリゲートを使用すると、次のように、渡された参照を操作することで、プロパティがアタッチされているコントロールに新しい機能を追加できます。

  1. propertyChanged のデリゲートによって、BindableObject として受け取られるコントロールの参照が、ビヘイビアーが強化されるように設計されたコントロールの種類にキャストされます。
  2. propertyChanged のデリゲートによってコントロールのプロパティ変更、コントロールのメソッド呼び出し、またはコントロールで公開されているイベントに対するイベント ハンドラーの登録が行われ、コア ビヘイビアー機能が実装されます。

警告

添付ビヘイビアーは、static プロパティおよびメソッドを使用して static クラスで定義されます。 そのため、状態があるアタッチされたビヘイビアーを作成することは困難です。

添付ビヘイビアーを作成する

添付ビヘイビアーは、propertyChanged デリゲートを指定する添付プロパティを含む静的クラスを作成することによって実装できます。

次の例は、ユーザーが Entry コントロールに入力した値が double でない場合、その値を赤で強調表示する AttachedNumericValidationBehavior クラスを示しています。

public static class AttachedNumericValidationBehavior
{
    public static readonly BindableProperty AttachBehaviorProperty =
        BindableProperty.CreateAttached("AttachBehavior", typeof(bool), typeof(AttachedNumericValidationBehavior), false, propertyChanged: OnAttachBehaviorChanged);

    public static bool GetAttachBehavior(BindableObject view)
    {
        return (bool)view.GetValue(AttachBehaviorProperty);
    }

    public static void SetAttachBehavior(BindableObject view, bool value)
    {
        view.SetValue(AttachBehaviorProperty, value);
    }

    static void OnAttachBehaviorChanged(BindableObject view, object oldValue, object newValue)
    {
        Entry entry = view as Entry;
        if (entry == null)
        {
            return;
        }

        bool attachBehavior = (bool)newValue;
        if (attachBehavior)
        {
            entry.TextChanged += OnEntryTextChanged;
        }
        else
        {
            entry.TextChanged -= OnEntryTextChanged;
        }
    }

    static void OnEntryTextChanged(object sender, TextChangedEventArgs args)
    {
        double result;
        bool isValid = double.TryParse(args.NewTextValue, out result);
        ((Entry)sender).TextColor = isValid ? Colors.Black : Colors.Red;
    }
}

AttachedNumericValidationBehavior クラスには、static getter と setter がある AttachBehavior という名前の添付プロパティが含まれています。このプロパティにより、それがアタッチされるコントロールの動作の追加または削除が制御されます。 この添付プロパティは、そのプロパティの値が変更されるときに実行される OnAttachBehaviorChanged デリゲートを登録します。 このメソッドによって、AttachBehavior 添付プロパティの値に基づいて TextChanged イベントのイベント ハンドラーが登録または登録解除されます。 OnEntryTextChanged メソッドによって動作のコア機能が提供され、ユーザーが Entry に入力した値を解析し、その値が double 以外の場合は TextColor プロパティを赤で表示するように設定します。

添付ビヘイビアーを使用する

添付ビヘイビアーは、ターゲット コントロールに添付プロパティを設定することで使用できます。

次の例は、AttachBehavior 添付プロパティを Entry に追加して、EntryAttachedNumericValidationBehavior クラスを使用する方法を示しています。


<ContentPage ...
             xmlns:local="clr-namespace:BehaviorsDemos">
    <Entry Placeholder="Enter a System.Double" local:AttachedNumericValidationBehavior.AttachBehavior="true" />
</ContentPage>

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

Entry entry = new Entry { Placeholder = "Enter a System.Double" };
AttachedNumericValidationBehavior.SetAttachBehavior(entry, true);

次のスクリーン ショットは、無効な入力に応答している添付ビヘイビアーを示しています。

Screenshot of attached behavior responding to invalid input

Note

アタッチされたビヘイビアーは特定のコントロールの種類 (または複数のコントロールに適用できるスーパークラス) に対して記述され、互換性のあるコントロールにのみ追加する必要があります。

添付ビヘイビアーを削除する

AttachedNumericValidationBehavior クラスは、AttachBehavior 添付プロパティを false に設定すると削除できます。

<Entry Placeholder="Enter a System.Double" local:AttachedNumericValidationBehavior.AttachBehavior="false" />

実行時に、AttachBehavior 添付プロパティの値が false に設定されていると、OnAttachBehaviorChanged メソッドが実行されます。 すると、OnAttachBehaviorChanged メソッドは、TextChanged イベントのイベント ハンドラーの登録を解除し、ユーザーがコントロールを操作してもその動作を実行できないようにします。

.NET MAUI ビヘイビアー

.NET MAUI ビヘイビアーは、Behavior または Behavior<T> クラスの派生クラスから作成されます。

.NET MAUI ビヘイビアーを作成するプロセスは次の通りです。

  1. Behavior または Behavior<T> クラスから継承されるクラスを作成します。T は、このビヘイビアーを適用するコントロールの種類です。
  2. 必要な設定を実行するように OnAttachedTo メソッドをオーバーライドします。
  3. 必要なクリーンアップを実行するように OnDetachingFrom メソッドをオーバーライドします。
  4. ビヘイビアーのコア機能を実装します。

これで、次の例に示す構造になります。

public class MyBehavior : Behavior<View>
{
    protected override void OnAttachedTo(View bindable)
    {
        base.OnAttachedTo(bindable);
        // Perform setup
    }

    protected override void OnDetachingFrom(View bindable)
    {
        base.OnDetachingFrom(bindable);
        // Perform clean up
    }

    // Behavior implementation
}

動作がコントロールにアタッチされると、すぐに OnAttachedTo メソッドが呼び出されます。 このメソッドがアタッチされているコントロールへの参照を受け取り、イベント ハンドラーの登録やビヘイビアー機能をサポートするために必要なその他の設定を実行するために使用できます。 たとえば、コントロールのイベントをサブスクライブできます。 その後、イベント用のイベント ハンドラー内にビヘイビアー機能を実装します。

動作がコントロールから削除されると、OnDetachingFrom メソッドが呼び出されます。 このメソッドがアタッチされているコントロールへの参照を受け取り、必要なクリーンアップを実行するために使用されます。 たとえば、メモリ リークを防ぐためにコントロールのイベントのサブスクライブを解除できます。

その後、コントロールの Behaviors コレクションにアタッチすることで、動作を使用できるようになります。

.NET MAUI ビヘイビアーを作成する

.NET MAUI ビヘイビアーは、Behavior または Behavior<T> から派生するクラスを作成し、OnAttachedTo メソッドと OnDetachingFrom メソッドをオーバーライドすることによって実装できます。

次の例は、ユーザーが Entry コントロールに赤色で入力した値が double ではない場合に NumericValidationBehavior クラスが強調表示するのを示しています。

public class NumericValidationBehavior : Behavior<Entry>
{
    protected override void OnAttachedTo(Entry entry)
    {
        entry.TextChanged += OnEntryTextChanged;
        base.OnAttachedTo(entry);
    }

    protected override void OnDetachingFrom(Entry entry)
    {
        entry.TextChanged -= OnEntryTextChanged;
        base.OnDetachingFrom(entry);
    }

    void OnEntryTextChanged(object sender, TextChangedEventArgs args)
    {
        double result;
        bool isValid = double.TryParse(args.NewTextValue, out result);
        ((Entry)sender).TextColor = isValid ? Colors.Black : Colors.Red;
    }
}

この例では、NumericValidationBehavior クラスは Behavior<T> クラスから派生し、そこでは、TEntry です。 OnAttachedTo メソッドにより、TextChanged イベント用のイベント ハンドラーが登録され、OnDetachingFrom メソッドにより、メモリ リークを防ぐために TextChanged の登録が解除されます。 OnEntryTextChanged メソッドによって動作のコア機能が提供され、ユーザーが Entry に入力した値を解析し、その値が double 以外の場合は TextColor プロパティを赤で表示するように設定します。

重要

動作は共有でき、スタイルから複数のコントロールに適用できるため、.NET MAUI では動作の BindingContext を設定しません。

.NET MAUI ビヘイビアーを使用する

すべての .NET MAUI コントロールには、1 つ以上の動作を追加できる Behaviors コレクションがあります。

<Entry Placeholder="Enter a System.Double">
    <Entry.Behaviors>
        <local:NumericValidationBehavior />
    </Entry.Behaviors>
</Entry>

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

Entry entry = new Entry { Placeholder = "Enter a System.Double" };
entry.Behaviors.Add(new NumericValidationBehavior());

次のスクリーンショットは、無効な入力に応答している.NET MAUI ビヘイビアーを示しています。

Screenshot of .NET MAUI behavior responding to invalid input

警告

.NET MAUI ビヘイビアーは特定のコントロール型 (または複数のコントロールに適用できるスーパークラス) 用に記述されているため、互換性のあるコントロールにのみ追加する必要があります。 互換性のないコントロールに.NET MAUI ビヘイビアーをアタッチしようとすると、例外がスローされます。

スタイルを使用して .NET MAUI ビヘイビアーを使用する

明示的または暗黙的なスタイルによって .NET MAUI ビヘイビアーを使用することもできます。 ただし、コントロールの Behaviors プロパティは読み取り専用であるため、このプロパティを設定するスタイルを作成することはできません。 解決策は、ビヘイビアーの追加と削除を制御する添付プロパティをビヘイビアー クラスに追加することです。 このプロセスは次のとおりです。

  1. 添付プロパティを動作クラスに添付します。この動作クラスは、動作がアタッチされるコントロールへの動作の追加または削除を制御するために使用されます。 この添付プロパティにより、プロパティの値が変更されたときに実行される propertyChanged デリゲートが確実に登録されるようにします。
  2. 添付プロパティの static ゲッターとセッターを作成します。
  3. propertyChanged デリゲートで、ビヘイビアーを追加または削除するロジックを実装します。

次の例は、動作の追加と削除を制御する添付プロパティを持つ NumericValidationStyleBehavior クラスを示しています。

public class NumericValidationStyleBehavior : Behavior<Entry>
{
    public static readonly BindableProperty AttachBehaviorProperty =
        BindableProperty.CreateAttached("AttachBehavior", typeof(bool), typeof(NumericValidationStyleBehavior), false, propertyChanged: OnAttachBehaviorChanged);

    public static bool GetAttachBehavior(BindableObject view)
    {
        return (bool)view.GetValue(AttachBehaviorProperty);
    }

    public static void SetAttachBehavior(BindableObject view, bool value)
    {
        view.SetValue(AttachBehaviorProperty, value);
    }

    static void OnAttachBehaviorChanged(BindableObject view, object oldValue, object newValue)
    {
        Entry entry = view as Entry;
        if (entry == null)
        {
            return;
        }

        bool attachBehavior = (bool)newValue;
        if (attachBehavior)
        {
            entry.Behaviors.Add(new NumericValidationStyleBehavior());
        }
        else
        {
            Behavior toRemove = entry.Behaviors.FirstOrDefault(b => b is NumericValidationStyleBehavior);
            if (toRemove != null)
            {
                entry.Behaviors.Remove(toRemove);
            }
        }
    }

    protected override void OnAttachedTo(Entry entry)
    {
        entry.TextChanged += OnEntryTextChanged;
        base.OnAttachedTo(entry);
    }

    protected override void OnDetachingFrom(Entry entry)
    {
        entry.TextChanged -= OnEntryTextChanged;
        base.OnDetachingFrom(entry);
    }

    void OnEntryTextChanged(object sender, TextChangedEventArgs args)
    {
        double result;
        bool isValid = double.TryParse(args.NewTextValue, out result);
        ((Entry)sender).TextColor = isValid ? Colors.Black : Colors.Red;
    }
}

この例では、NumericValidationStyleBehavior クラスには、static getter と setter を持つ AttachBehavior という名前の添付プロパティが含まれています。このプロパティにより、アタッチされるコントロールに対する動作の追加または削除が制御されます。 この添付プロパティは、そのプロパティの値が変更されるときに実行される OnAttachBehaviorChanged デリゲートを登録します。 このメソッドでは、AttachBehavior 添付プロパティの値に基づいて、ビヘイビアーの追加または削除が行われます。

次のコード例で、AttachBehavior 添付プロパティを使用する NumericValidationStyleBehavior 用の "明示的な" スタイルで、Entry コントロールに適用できるものを示します。

<Style x:Key="NumericValidationStyle" TargetType="Entry">
    <Style.Setters>
        <Setter Property="local:NumericValidationStyleBehavior.AttachBehavior" Value="true" />
    </Style.Setters>
</Style>

StaticResource マークアップ拡張機能を使用してスタイルに Style プロパティを設定することで、StyleEntry に適用できます。

<Entry Placeholder="Enter a System.Double" Style="{StaticResource NumericValidationStyle}">

スタイルの詳細については、 のスタイルに関するページを参照してください。

Note

XAML で設定されているかクエリを実行するビヘイビアーにバインド可能プロパティを追加できますが、状態があるビヘイビアーを作成する場合は、ResourceDictionaryStyle スタイルに含まれるコントロール間でそれらを共有しないでください。

.NET MAUI ビヘイビアーを削除する

動作からコントロールが削除されると、OnDetachingFrom メソッドが呼び出されます。これを使用して、メモリ リークを防ぐために、イベントのサブスクライブ解除などの必要なクリーンアップを実行します。 ただし、コントロールの Behaviors コレクションが Remove または Clear メソッドによって変更されない限り、動作がコントロールから暗黙的に削除されることはありません。

Behavior toRemove = entry.Behaviors.FirstOrDefault(b => b is NumericValidationStyleBehavior);
if (toRemove != null)
{
    entry.Behaviors.Remove(toRemove);
}

または、コントロールの Behaviors コレクションをクリアできます。

entry.Behaviors.Clear();

Note

ナビゲーション スタックからページがポップアップ表示される際、.NET MAUI ビヘイビアーがコントロールから暗黙的に削除されることはありません。 代わりに、ページがスコープを外れる前に、明示的に削除する必要があります。

プラットフォームの動作

プラットフォームの動作は、PlatformBehavior<TView> または PlatformBehavior<TView,TPlatformView> クラスから派生して作成されます。 ネイティブ コントロールの任意の条件とイベントに応答します。

プラットフォームの動作は、条件付きコンパイルまたは部分クラスを使用して実装できます。 ここで採用するアプローチは、部分クラスを使用することです。プラットフォームの動作は、通常、動作 API を定義するクロスプラットフォーム部分クラスと、各プラットフォームで動作を実装するネイティブ部分クラスで構成されます。 ビルド時に、マルチターゲットは部分クラスを組み合わせて、各プラットフォームでプラットフォームの動作を構築します。

プラットフォームの動作を作成するプロセスは次のとおりです。

  1. プラットフォーム動作の API を定義するクロスプラットフォーム部分クラスを作成します。

  2. クロスプラットフォーム部分クラスと同じ名前を持つ、アプリがビルドされている各プラットフォームでネイティブ部分クラスを作成します。 このネイティブ部分クラスは、PlatformBehavior<TView> または PlatformBehavior<TView,TPlatformView> クラスから継承する必要があります。このクラスでは、TView は動作が適用されるクロスプラットフォーム コントロールであり、TPlatformView は特定のプラットフォームでクロスプラットフォーム コントロールを実装するネイティブ ビューです。

    Note

    アプリがビルドされている各プラットフォームでネイティブ部分クラスを作成する必要がある一方で、プラットフォームの動作機能をすべてのプラットフォームに実装する必要はありません。 たとえば、すべてのプラットフォームではなく、一部のプラットフォームでネイティブ コントロールの境界線の太さを変更するプラットフォーム動作を作成できます。

  3. プラットフォームの動作を実装するために必要な各ネイティブ部分クラスでは、次の操作を行う必要があります。

    1. 必要な設定を実行するように OnAttachedTo メソッドをオーバーライドします。
    2. 必要なクリーンアップを実行するように OnDetachedFrom メソッドをオーバーライドします。
    3. プラットフォーム動作のコア機能を実装します。

その後、コントロールの Behaviors コレクションにアタッチすることで、動作を使用できるようになります。

プラットフォームの動作を作成する

プラットフォームの動作を作成するには、まず、プラットフォームの動作の API を定義するクロスプラットフォーム部分クラスを作成する必要があります。

namespace BehaviorsDemos
{
    public partial class TintColorBehavior
    {
        public static readonly BindableProperty TintColorProperty =
            BindableProperty.Create(nameof(TintColor), typeof(Color), typeof(TintColorBehavior));

        public Color TintColor
        {
            get => (Color)GetValue(TintColorProperty);
            set => SetValue(TintColorProperty, value);
        }
    }
}

プラットフォームの動作は、同じ名前を使用する追加の部分クラスを使用して、必要な各プラットフォームで実装が完了する部分クラスです。 この例では、TintColorBehavior クラスは、指定された色で画像に色を付ける単一のバインド可能なプロパティである TintColor を定義します。

クロスプラットフォーム部分クラスを作成したら、アプリをビルドする各プラットフォームでネイティブ部分クラスを作成する必要があります。 これは、プラットフォーム フォルダーの必要な子フォルダーに部分クラスを追加することで実現できます。

Screenshot of the native partial classes for a platform behavior.

または、ファイル名に基づくマルチターゲット、フォルダーに基づくマルチターゲット、またはその両方をサポートするようにプロジェクトを構成することもできます。 マルチターゲットの詳細については、「マルチターゲットの構成」をご覧ください。

ネイティブ部分クラスは、PlatformBehavior<TView> クラスまたは PlatformBehavior<TView,TPlatformView> クラスから継承する必要があります。このクラスでは、TView は動作を適用するクロスプラットフォーム コントロールであり、TPlatformView は特定のプラットフォームにクロスプラットフォーム コントロールを実装するネイティブ ビューです。 プラットフォームの動作を実装するために必要な各ネイティブ部分クラスでは、OnAttachedTo メソッドと OnDetachedFrom メソッドをオーバーライドし、プラットフォームの動作のコア機能を実装する必要があります。

プラットフォームの動作がクロスプラットフォーム コントロールにアタッチされると、すぐに OnAttachedTo メソッドが呼び出されます。 メソッドは、アタッチ先のクロスプラットフォーム コントロールへの参照と、必要に応じてクロスプラットフォーム コントロールを実装するネイティブ コントロールへの参照を受け取ります。 このメソッドを使用して、イベント ハンドラーの登録やプラットフォーム動作機能をサポートするために必要なその他の設定を実行できます。 たとえば、コントロールのイベントをサブスクライブできます。 その後、イベント用のイベント ハンドラー内にビヘイビアー機能を実装します。

クロスプラットフォーム コントロールから動作が削除されると、OnDetachedFrom メソッドが呼び出されます。 メソッドは、アタッチ先のコントロールへの参照と、必要に応じてクロスプラットフォーム コントロールを実装するネイティブ コントロールへの参照を受け取ります。 メソッドを使用して必要なクリーンアップが実行されるようにします。 たとえば、メモリ リークを防ぐためにコントロールのイベントのサブスクライブを解除できます。

重要

部分クラスは同じ名前空間に存在し、同じ名前を使用する必要があります。

次の例は、Android の TintColorBehavior 部分クラスを示しています。これは、指定された色で画像に色を付けます。

using Android.Graphics;
using Android.Widget;
using Microsoft.Maui.Platform;
using Color = Microsoft.Maui.Graphics.Color;

namespace BehaviorsDemos
{
    public partial class TintColorBehavior : PlatformBehavior<Image, ImageView>
    {
        protected override void OnAttachedTo(Image bindable, ImageView platformView)
        {
            base.OnAttachedTo(bindable, platformView);

            if (bindable is null)
                return;
            if (TintColor is null)
                ClearColor(platformView);
            else
                ApplyColor(platformView, TintColor);
        }

        protected override void OnDetachedFrom(Image bindable, ImageView platformView)
        {
            base.OnDetachedFrom(bindable, platformView);

            if (bindable is null)
                return;
            ClearColor(platformView);
        }

        void ApplyColor(ImageView imageView, Color color)
        {
            imageView.SetColorFilter(new PorterDuffColorFilter(color.ToPlatform(), PorterDuff.Mode.SrcIn ?? throw new NullReferenceException()));
        }

        void ClearColor(ImageView imageView)
        {
            imageView.ClearColorFilter();
        }
    }
}

この例では、TintColorBehavior クラスは PlatformBehavior<TView,TPlatformView> クラスから派生します。ここでは、TViewImage で、TPlatformViewImageView です。 TintColor プロパティに値がある場合は、OnAttachedTo は画像に色を付けます。 OnDetachedFrom メソッドは、画像から淡い色を削除します。

アプリをビルドするプラットフォームごとに、ネイティブ部分クラスを追加する必要があります。 ただし、プラットフォームの動作が特定のプラットフォームで必要ない場合は、ネイティブ部分クラス NO-OP を作成できます。 これを行うには、空のクラスを指定します。

using Microsoft.UI.Xaml;

namespace BehaviorsDemos
{
    public partial class TintColorBehavior : PlatformBehavior<Image, FrameworkElement>
    {
        // NO-OP on Windows
    }
}

重要

.NET MAUI では、プラットフォーム動作の BindingContext は設定されません。

プラットフォームの動作を使用する

すべての .NET MAUI コントロールには Behaviors コレクションがあり、それに 1 つ以上のプラットフォーム動作を追加できます。

<Image Source="dotnet_bot.png"
       HeightRequest="200"
       HorizontalOptions="Center">
    <Image.Behaviors>
        <local:TintColorBehavior TintColor="Red" />
    </Image.Behaviors>
</Image>

C# での同等の Image を次の例に示します。

Image image = new Image { Source = "dotnet_bot.png", HeightRequest = 200, HorizontalOptions = LayoutOptions.Center };
image.Behaviors.Add(new TintColorBehavior());

次のスクリーンショットは、イメージの濃淡を設定するプラットフォームの動作を示しています。

Screenshot of .NET MAUI platform behavior tinting an image.

警告

プラットフォーム動作は特定のコントロールの型 (または複数のコントロールに適用できるスーパークラス) に対して記述され、互換性のあるコントロールにのみ追加する必要があります。 互換性のないコントロールにプラットフォーム動作をアタッチしようとすると、例外がスローされます。