共用方式為


行為

Browse sample. 流覽範例

.NET 多平臺應用程式 UI (.NET MAUI) 行為可讓您將功能新增至使用者介面控件,而不需要將其子類別化。 相反地,功能會在行為類別中實作並附加至控制項,如同控制項本身的一部分。

行為可讓您實作您通常必須撰寫為程式碼後置的程式碼,因為此程式碼直接與控制項的 API 互動,所以透過此方式可以精確附加至控制項並封裝,以供多個應用程式重複使用。 可用來提供各種功能給控制項,例如:

  • 將電子郵件驗證程式新增至 Entry
  • 建立使用點選手勢辨識器的評等控制項。
  • 控制動畫。

.NET MAUI 支援三種不同類型的行為:

附加行為

附加的行為是具有一或多個附加屬性的靜態類別。 附加屬性是可繫結屬性的特殊類型。 它們會定義於一個類別但附加至其他物件,而且在 XAML 中會識別為包含類別和屬性名稱並以句號分隔的屬性。 如需附加屬性的詳細資訊,請參閱 附加屬性

附加屬性可定義 propertyChanged 委派。當屬性的值變更時 (例如當設定控制項的屬性時),就會執行此委派。 當 propertyChanged 委派執行時,會將其附加至的控制項參考,以及包含屬性新舊值的參數傳遞給該委派。 您可以使用此委派,透過操作傳入的參考來將新功能新增至屬性所附加的控制項,如下所示:

  1. propertyChanged 委派會將以 BindableObject 形式接收的控制項參考,轉換為其行為旨在增強的控制項類型。
  2. propertyChanged 委派會修改控制項的屬性、呼叫控制項的方法,或註冊控制項所公開事件的事件處理常式,以便實作核心行為功能。

警告

附加行為是在類別中 static 定義,並具有 static 屬性和方法。 這點會讓您難以建立具有狀態的附加行為。

建立附加行為

藉由建立包含指定 propertyChanged 委派之附加屬性的靜態類別,即可實作附加行為。

下列範例顯示 AttachedNumericValidationBehavior 類別,如果double不是 ,則會將使用者輸入的值反白顯示為Entry紅色的控件:

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 包含名為 AttachBehavior 且具有 static getter 和 setter 的附加屬性,可控制將附加至控件的加入或移除行為。 此附加屬性會註冊 OnAttachBehaviorChanged 方法;當屬性的值變更時,就會執行此方法。 此方法會根據 AttachBehavior 附加屬性的值,註冊或取消註冊 TextChanged 事件的事件處理常式。 行為的核心功能是由 OnEntryTextChanged 方法提供,它會剖析 中Entry輸入的值,如果值不是 double,則TextColor屬性會設定為紅色。

取用附加行為

藉由在目標控件上設定附加屬性,即可取用附加行為。

下列範例示範將附加屬性新增AttachBehaviorEntry,以在 AttachedNumericValidationBehavior 上使用 Entry 類別:


<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

注意

附加的行為是針對特定控制項類型 (或可套用至許多控制項的子類別) 所撰寫,而且只應新增至相容的控制項。

拿掉附加行為

AttachedNumericValidationBehavior附加屬性false設定AttachBehavior為 ,即可從控制項移除 類別:

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

在執行階段,當 AttachBehavior 附加屬性的值設定為 false 時,將會執行 OnAttachBehaviorChanged 方法。 OnAttachBehaviorChanged方法接著會取消登錄事件的事件處理程式TextChanged,確保行為不會在您與控件互動時執行。

.NET MAUI 行為

.NET MAUI 行為是由 衍生自 BehaviorBehavior<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 行為

建立衍生自 或 類別的Behavior類別,並覆寫 OnAttachedToOnDetachingFrom 方法,即可實作 .NET MAUI Behavior<T> 行為。

下列範例顯示 NumericValidationBehavior 類別,如果double不是 ,則會將使用者輸入的值反白顯示為Entry紅色的控件:

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> 類別,其中 TEntryOnAttachedTo 方法會註冊 TextChanged 事件的事件處理常式,以 OnDetachingFrom 方法取消註冊 TextChanged 事件來防止記憶體流失。 行為的核心功能是由 OnEntryTextChanged 方法提供,它會剖析 中Entry輸入的值,如果值不是 double,則TextColor屬性會設定為紅色。

重要

.NET MAUI 不會設定 BindingContext 行為,因為行為可以透過樣式共用並套用至多個控件。

取用 .NET MAUI 行為

每個 .NET MAUI 控制件都有一個 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 getter 和 setter。
  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 包含名為 AttachBehavior 且具有 static getter 和 setter 的附加屬性,可控制將附加至控件的加入或移除行為。 此附加屬性會註冊 OnAttachBehaviorChanged 方法;當屬性的值變更時,就會執行此方法。 此方法會根據 AttachBehavior 附加屬性的值,新增或移除控制項的行為。

下列程式碼範例示範使用 AttachBehavior 附加屬性之 NumericValidationStyleBehavior 的「明確」樣式,且可套用至 Entry 控制項:

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

Style可以使用標記延伸,將其 Style 屬性設定為Entry樣式,以套用StaticResource至 :

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

如需樣式的詳細資訊,請參閱樣式

注意

如果您確實建立了其狀態不應該在 ResourceDictionaryStyle 控制項之間共用的行為,則您可以將可繫結的屬性新增至使用 XAML 所設定或查詢的行為。

拿掉 .NET MAUI 行為

OnDetachingFrom從控件移除行為時會呼叫 方法,並用來執行任何必要的清除,例如取消訂閱事件以防止記憶體流失。 不過,除非 或 Clear 方法修改Remove控件的Behaviors集合,否則不會隱含地從控件中移除行為:

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

或者,可以清除控件的 Behaviors 集合:

entry.Behaviors.Clear();

注意

當頁面從流覽堆疊彈出時,不會從控件隱含移除 .NET MAUI 行為。 而是必須在頁面超出範圍之前先明確移除它們。

平台行為

平台行為是由衍生自 PlatformBehavior<TView>PlatformBehavior<TView,TPlatformView> 類別所建立。 它們會回應原生控件上的任意條件和事件。

平台行為可以透過條件式編譯或部分類別來實作。 此處採用的方法是使用部分類別,其中平臺行為通常包含定義行為 API 的跨平臺部分類別,以及在每個平臺上實作行為的原生部分類別。 在建置階段,多重目標結合部分類別,在每個平臺上建置平台行為。

建立平台行為的程式如下所示:

  1. 建立跨平臺部分類別,以定義平台行為的 API。

  2. 在您的應用程式建置的每個平臺上建立原生部分類別,其名稱與跨平臺部分類別相同。 這個原生部分類別應該繼承自 PlatformBehavior<TView>PlatformBehavior<TView,TPlatformView> 類別,其中 TView 是應該套用行為的跨平臺控件,而 TPlatformView 是在特定平台上實作跨平臺控件的原生檢視。

    注意

    雖然您必須在建置應用程式的每個平臺上建立原生部分類別,但不需要在每個平台上實作平台行為功能。 例如,您可能會建立一個平台行為,以修改某些平臺上原生控件的框線粗細,但並非全部。

  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 跨平臺控件移除行為時,會呼叫 方法。 方法會接收所附加控件的參考,以及選擇性地參考實作跨平臺控件的原生控件。 方法應該用來執行任何必要的清除。 例如,您可以取消訂閱控制項上的事件來防止記憶體流失。

重要

部分類別必須位於相同的命名空間,並使用相同的名稱。

下列範例顯示 TintColorBehavior Android 的部分類別,其會以指定的色彩標示影像:

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> 類別,其中 TView 是 ,而 TPlatformViewImage ImageView。 如果 屬性具有 值,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 集合,可以新增一或多個平台行為:

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

警告

平臺行為是針對特定控制項類型所撰寫的(或可以套用至許多控制項的超級類別),而且應該只新增至相容的控制項。 嘗試將平臺行為附加至不相容的控制項會導致擲回例外狀況。