行為
.NET 多平臺應用程式 UI (.NET MAUI) 行為可讓您將功能新增至使用者介面控件,而不需要將其子類別化。 相反地,功能會在行為類別中實作並附加至控制項,如同控制項本身的一部分。
行為可讓您實作您通常必須撰寫為程式碼後置的程式碼,因為此程式碼直接與控制項的 API 互動,所以透過此方式可以精確附加至控制項並封裝,以供多個應用程式重複使用。 可用來提供各種功能給控制項,例如:
- 將電子郵件驗證程式新增至 Entry。
- 建立使用點選手勢辨識器的評等控制項。
- 控制動畫。
.NET MAUI 支援三種不同類型的行為:
- 附加行為是具有一或多個附加屬性的
static
類別。 如需附加行為的詳細資訊,請參閱 附加行為。 - .NET MAUI 行為是衍生自 Behavior 或 Behavior<T> 類別的類別,其中
T
是應該套用行為的控件類型。 如需詳細資訊,請參閱 .NET MAUI 行為。 - 平台行為是衍生自 或 PlatformBehavior<TView,TPlatformView> 類別的PlatformBehavior<TView>類別。 這些行為可以回應原生控件上的任意條件和事件。 如需詳細資訊,請參閱 平台行為。
附加行為
附加的行為是具有一或多個附加屬性的靜態類別。 附加屬性是可繫結屬性的特殊類型。 它們會定義於一個類別但附加至其他物件,而且在 XAML 中會識別為包含類別和屬性名稱並以句號分隔的屬性。 如需附加屬性的詳細資訊,請參閱 附加屬性。
附加屬性可定義 propertyChanged
委派。當屬性的值變更時 (例如當設定控制項的屬性時),就會執行此委派。 當 propertyChanged
委派執行時,會將其附加至的控制項參考,以及包含屬性新舊值的參數傳遞給該委派。 您可以使用此委派,透過操作傳入的參考來將新功能新增至屬性所附加的控制項,如下所示:
propertyChanged
委派會將以 BindableObject 形式接收的控制項參考,轉換為其行為旨在增強的控制項類型。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
屬性會設定為紅色。
取用附加行為
藉由在目標控件上設定附加屬性,即可取用附加行為。
下列範例示範將附加屬性新增AttachBehavior
至 Entry,以在 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);
下列螢幕快照顯示回應無效輸入的附加行為:
注意
附加的行為是針對特定控制項類型 (或可套用至許多控制項的子類別) 所撰寫,而且只應新增至相容的控制項。
拿掉附加行為
將AttachedNumericValidationBehavior
附加屬性false
設定AttachBehavior
為 ,即可從控制項移除 類別:
<Entry Placeholder="Enter a System.Double" local:AttachedNumericValidationBehavior.AttachBehavior="false" />
在執行階段,當 AttachBehavior
附加屬性的值設定為 false
時,將會執行 OnAttachBehaviorChanged
方法。 OnAttachBehaviorChanged
方法接著會取消登錄事件的事件處理程式TextChanged
,確保行為不會在您與控件互動時執行。
.NET MAUI 行為
.NET MAUI 行為是由 衍生自 Behavior 或 Behavior<T> 類別所建立。
建立 .NET MAUI 行為的程式如下所示:
- 建立繼承自 Behavior 或是 Behavior<T> 類別的類別,其中
T
是應該套用行為的控制項類型。 - 覆寫 OnAttachedTo 方法,以執行任何必要的設定。
- 覆寫 OnDetachingFrom 方法,以執行任何必要的清除。
- 實作行為的核心功能。
這會導致下列範例所示的結構:
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類別,並覆寫 OnAttachedTo 和 OnDetachingFrom 方法,即可實作 .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> 類別,其中 T
是 Entry。 OnAttachedTo 方法會註冊 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 行為:
警告
.NET MAUI 行為是針對特定控件類型所撰寫的(或可以套用至許多控件的超級類別),而且應該只新增至相容的控件。 嘗試將 .NET MAUI 行為附加至不相容的控件會導致擲回例外狀況。
使用樣式取用 .NET MAUI 行為
.NET MAUI 行為可由明確或隱含樣式取用。 但不能建立可設定控制項之 Behaviors 屬性的樣式,因為屬性為唯讀。 解決方案是將附加屬性新增至會控制新增和移除行為的行為類別。 此程序如下:
- 將附加屬性新增至行為類別,這個類別將用來控制將附加行為的控件加入或移除行為。 請確保此附加屬性會註冊
propertyChanged
委派,當屬性值變更時,就會執行此委派。 - 建立附加屬性的
static
getter 和 setter。 - 實作
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}">
如需樣式的詳細資訊,請參閱樣式。
注意
如果您確實建立了其狀態不應該在 ResourceDictionary 的 Style 控制項之間共用的行為,則您可以將可繫結的屬性新增至使用 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 的跨平臺部分類別,以及在每個平臺上實作行為的原生部分類別。 在建置階段,多重目標結合部分類別,在每個平臺上建置平台行為。
建立平台行為的程式如下所示:
建立跨平臺部分類別,以定義平台行為的 API。
在您的應用程式建置的每個平臺上建立原生部分類別,其名稱與跨平臺部分類別相同。 這個原生部分類別應該繼承自 PlatformBehavior<TView> 或 PlatformBehavior<TView,TPlatformView> 類別,其中
TView
是應該套用行為的跨平臺控件,而TPlatformView
是在特定平台上實作跨平臺控件的原生檢視。注意
雖然您必須在建置應用程式的每個平臺上建立原生部分類別,但不需要在每個平台上實作平台行為功能。 例如,您可能會建立一個平台行為,以修改某些平臺上原生控件的框線粗細,但並非全部。
在每個需要實作平台行為的原生部分類別中,您應該:
- 覆寫 OnAttachedTo 方法以執行任何設定。
- OnDetachedFrom覆寫 方法以執行任何清除。
- 實作平台行為的核心功能。
接著,可以將它附加至 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
會使用指定的色彩來淡化影像。
建立跨平臺部分類別之後,您應該在建置應用程式的每個平臺上建立原生部分類別。 這可以藉由將部分類別新增至 [平臺] 資料夾的必要子資料夾來完成:
或者,您可以設定專案以支援以檔名為基礎的多重目標,或資料夾型多重目標,或兩者。 如需多重目標的詳細資訊,請參閱 設定多重目標。
原生部分類別應該繼承自 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
是 ,而 TPlatformView
是 Image 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());
下列螢幕快照顯示平台行為著色影像:
警告
平臺行為是針對特定控制項類型所撰寫的(或可以套用至許多控制項的超級類別),而且應該只新增至相容的控制項。 嘗試將平臺行為附加至不相容的控制項會導致擲回例外狀況。