Xamarin.Forms 行为是通过从 Behavior 或 Behavior<T> 类派生来创建的。 本文演示如何创建和使用 Xamarin.Forms 行为。
概述
创建 Xamarin.Forms 行为的过程如下所示:
- 创建一个继承自
Behavior或Behavior<T>类的类,其中T是施加该行为的控件类型。 - 重写
OnAttachedTo方法以执行任何所需设置。 - 重写
OnDetachingFrom方法以执行任何所需清理。 - 实现行为的核心功能。
这将导致以下代码示例所示的结构:
public class CustomBehavior : 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 集合来使用该行为。
创建 Xamarin.Forms 行为
示例应用程序演示一个 NumericValidationBehavior,并用红色突出显示用户输入到 Entry 控件的值(如果该值不是 double)。 此行为如下面的代码示例所示:
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 ? Color.Default : Color.Red;
}
}
NumericValidationBehavior 派生自 Behavior<T> 类,其中 T 是 Entry。 OnAttachedTo 方法注册 TextChanged 事件的事件处理程序,并使用 OnDetachingFrom 方法注销 TextChanged 事件以防止内存泄漏。 该行为的核心功能由 OnEntryTextChanged 方法提供,该方法将用户输入的值解析为 Entry,如果该值不是 double,则将 TextColor 属性设置为红色。
注意
Xamarin.Forms 不会设置行为的 BindingContext,因为可以通过样式共享行为并将其应用于多个控件。
使用 Xamarin.Forms 行为
每个 Xamarin.Forms 控件都有一个 Behaviors 集合,其中可以添加一个或多个行为,如以下 XAML 代码示例所示:
<Entry Placeholder="Enter a System.Double">
<Entry.Behaviors>
<local:NumericValidationBehavior />
</Entry.Behaviors>
</Entry>
下面的代码示例介绍了 C# 中的等效 Entry:
var entry = new Entry { Placeholder = "Enter a System.Double" };
entry.Behaviors.Add (new NumericValidationBehavior ());
在运行时,根据行为实现,行为将响应与控件的交互。 以下屏幕截图演示了响应无效输入的行为:
注意
行为是为特定的控件类型(或者可以应用于许多控件的超类)编写的,它们只应添加到兼容的控件中。 试图将行为附加到不兼容控件将引发异常。
使用具有样式的 Xamarin.Forms 行为
行为也可以通过显式或隐式样式使用。 但是,不能创建设置控件的 Behaviors 属性的样式,因为该属性只读。 解决方案是向行为类添加附加属性,以控制添加和删除行为。 过程如下:
- 将附加属性添加到行为类中,以控制将附加行为的控件添加行为和删除行为。 确保附加的属性注册
propertyChanged委托,该委托将在属性值更改时执行。 - 为附加属性创建
staticgetter 和 setter。 - 在
propertyChanged委托中实现逻辑以添加和删除行为。
下面的代码示例显示了一个附加属性,用于控制添加和删除 NumericValidationBehavior:
public class NumericValidationBehavior : Behavior<Entry>
{
public static readonly BindableProperty AttachBehaviorProperty =
BindableProperty.CreateAttached ("AttachBehavior", typeof(bool), typeof(NumericValidationBehavior), 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)
{
var entry = view as Entry;
if (entry == null) {
return;
}
bool attachBehavior = (bool)newValue;
if (attachBehavior) {
entry.Behaviors.Add (new NumericValidationBehavior ());
} else {
var toRemove = entry.Behaviors.FirstOrDefault (b => b is NumericValidationBehavior);
if (toRemove != null) {
entry.Behaviors.Remove (toRemove);
}
}
}
...
}
NumericValidationBehavior 类包含带有 static getter 和 setter 且名为 AttachBehavior 的附加属性,该属性控制将附加行为的控件添加和删除行为。 该附加属性注册属性值更改时执行的 OnAttachBehaviorChanged 方法。 该方法根据 AttachBehavior 附加属性的值向控件添加或移除行为。
下面的代码示例显示使用 AttachBehavior 附加属性的 NumericValidationBehavior 的显式样式,该样式可应用于 Entry 控件:
<Style x:Key="NumericValidationStyle" TargetType="Entry">
<Style.Setters>
<Setter Property="local:NumericValidationBehavior.AttachBehavior" Value="true" />
</Style.Setters>
</Style>
Style 通过使用 StaticResource 标记扩展将其 Style 属性设置为 Style 实例使其可应用于 Entry 控件,如以下代码示例所示:
<Entry Placeholder="Enter a System.Double" Style="{StaticResource NumericValidationStyle}">
有关样式的详细信息,请参阅 样式。
注意
虽然可以向 XAML 中设置或查询的行为添加可绑定属性,但如果你确实创建了有状态的行为,则这些行为不应该在 ResourceDictionary 的Style 中的控件之间共享。
从控件中删除行为
当从控件中删除某个行为时,将触发 OnDetachingFrom 方法,该方法用于执行任何所需的清理,例如取消对事件的订阅,以防止内存泄漏。 但是,除非控件的 Behaviors 集合被 Remove 或 Clear 方法修改,否则行为不会从控件中隐式删除。 以下代码示例演示了如何从控件的 Behaviors 集合中删除特定的行为:
var toRemove = entry.Behaviors.FirstOrDefault (b => b is NumericValidationBehavior);
if (toRemove != null) {
entry.Behaviors.Remove (toRemove);
}
或者,可以清除控件的 Behaviors 集合,如下面的代码示例所示:
entry.Behaviors.Clear();
此外,请注意,当从导航堆栈中弹出页面时,行为不会从控件中隐式删除。 相反,必须在页面超出范围之前显式删除它们。
总结
本文演示如何创建和使用 Xamarin.Forms 行为。 Xamarin.Forms 行为由 Behavior 或 Behavior<T> 类派生创建而成。
