行为
触发器和行为通常是串联讨论的,因为它们具有一些应用重叠。 有时候你会感到困惑是否使用触发器或行为,因为似乎要么这样做
工作。
你可以用触发器做任何事情,你也可以做一个行为。 但是,行为总是涉及一些代码,这是一个派生自Behavior 的类。 如果您正在为EventTrigger编写Action 派生词,或者为其他触发器的EnterActions或ExitActions集合编写,则触发器仅涉及代码。
显然,如果您可以使用其中一个触发器执行所需操作而无需编写任何代码,则不要使用行为。 但有时它并不那么清楚。
让我们比较执行相同工作的触发器和行为。
本章前面显示的TriggerEntryValidation程序使用一个名为NumericEntryAction的类,它检查输入到Entry视图中的数字是否有资格作为有效的double值,如果不是,则将文本设置为红色:
namespace Xamarin.FormsBook.Toolkit
{
public class NumericValidationAction : TriggerAction<Entry>
{
protected override void Invoke(Entry entry)
{
double result;
bool isValid = Double.TryParse(entry.Text, out result);
entry.TextColor = isValid ? Color.Default : Color.Red;
}
}
}
这是在附加到条目的EventTrigger中引用的:
<Entry Placeholder="Enter a System.Double">
<Entry.Triggers>
<EventTrigger Event="TextChanged">
<toolkit:NumericValidationAction />
</EventTrigger>
</Entry.Triggers>
</Entry>
您可以对同一作业使用行为。 第一步是从Behavior 派生一个类。 泛型参数是行为可以处理的最通用的基类。 在这个例子中,这是一个Entry视图。 然后,重写两个名为OnAttachedTo和OnDetachingFrom的虚拟方法。 当行为附加到特定可视对象时,将调用OnAttachedTo方法,并为您的行为提供初始化自身的机会。 通常这涉及将一些事件处理程序附加到对象。 从可视对象中删除行为时,将调用OnDetachingFrom方法。 即使仅在程序终止时发生这种情况,您也应该撤消OnAttachedTo方法所做的任何事情。
这是NumericValidationBehavior类:
namespace Xamarin.FormsBook.Toolkit
{
public class NumericValidationBehavior : Behavior<Entry>
{
protected override void OnAttachedTo(Entry entry)
{
base.OnAttachedTo(entry);
entry.TextChanged += OnEntryTextChanged;
}
protected override void OnDetachingFrom(Entry entry)
{
base.OnDetachingFrom(entry);
entry.TextChanged -= OnEntryTextChanged;
}
void OnEntryTextChanged(object sender, TextChangedEventArgs args)
{
double result;
bool isValid = Double.TryParse(args.NewTextValue, out result);
((Entry)sender).TextColor = isValid ? Color.Default : Color.Red;
}
}
}
OnAttachedTo方法为Entry的TextChanged事件附加处理程序,OnDetachingFrom方法分离该处理程序。 处理程序本身与NumericValidationAction中的Invoke方法执行相同的工作。
因为NumericValidationBehavior类安装TextChanged事件的处理程序,所以可以使用该行为而不指定类名以外的任何内容。 这是BehaviorEntryValidation程序的XAML文件,它与使用EventTrigger的早期程序不同,它通过指定应用于四个Entry视图的隐式样式的行为:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:toolkit=
"clr-namespace:Xamarin.FormsBook.Toolkit;assembly=Xamarin.FormsBook.Toolkit"
x:Class="BehaviorEntryValidation.BehaviorEntryValidationPage"
Padding="50">
<ContentPage.Resources>
<ResourceDictionary>
<Style TargetType="Entry">
<Style.Behaviors>
<toolkit:NumericValidationBehavior />
</Style.Behaviors>
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout>
<Entry Placeholder="Enter a System.Double" />
<Entry Placeholder="Enter a System.Double" />
<Entry Placeholder="Enter a System.Double" />
<Entry Placeholder="Enter a System.Double" />
</StackLayout>
</ContentPage>
此Style对象在四个Entry视图中共享,因此只实例化一个NumericValidationBehavior对象。 由于此单个对象附加到四个Entry视图中的每一个,因此它会在每个视图上附加一个TextChanged处理程序,以便单个NumericValidationBehavior对象在四个视图上独立运行:
在这个特定的例子中,TriggerAction比行为更受欢迎,因为它代码较少而代码不引用特定事件,因此它更加通用。
但是行为可以像您想要的那样一般化或特定,行为也可以通过数据绑定更全面地参与XAML文件。