可重用的EventToCommandBehavior
事件触发时调用命令
行为可用于将命令与未设计为与命令交互的控件相关联。本文演示如何在事件触发时使用Xamarin.Forms行为来调用命令。
概观
该EventToCommandBehavior
班是响应执行命令,可重复使用的Xamarin.Forms定制行为的任何事件触发。默认情况下,该事件的事件参数将被传递给该命令,并且可以由一个IValueConverter
实现来选择转换。
为了使用该行为,必须设置以下行为属性:
- EventName - 行为侦听的事件的名称。
- 命令 - 要执行的ICommand。该行为期望在附加的控件
ICommand
上找到BindingContext
可以从父元素继承的实例。
还可以设置以下可选行为属性:
- CommandParameter -
object
将传递给命令的命令。 - 转换器 - 一种
IValueConverter
实现,它将通过绑定引擎在源和目标之间传递时更改事件参数数据的格式。
创建行为
这个EventToCommandBehavior
课程来自BehaviorBase<T>
班级,这又从Behavior<T>
课堂上得出。BehaviorBase<T>
该类的目的是为需要BindingContext
将该行为设置为附加控件的任何Xamarin.Forms行为提供基类。这样可以确保在行为消耗时,该行为可以绑定到ICommand
该Command
属性并执行该属性。
的BehaviorBase<T>
类提供一个可重写的OnAttachedTo
,其设定方法BindingContext
的行为和可重写的OnDetachingFrom
该清理方法BindingContext
。此外,该类存储对AssociatedObject
属性中附加控件的引用。
实施可绑定属性
为了在事件触发时执行用户定义的命令,EventToCommandBehavior
该类定义了四个BindableProperty
实例,如以下代码示例所示:
public class EventToCommandBehavior : BehaviorBase<View>
{
public static readonly BindableProperty EventNameProperty =
BindableProperty.Create ("EventName", typeof(string), typeof(EventToCommandBehavior), null, propertyChanged: OnEventNameChanged);
public static readonly BindableProperty CommandProperty =
BindableProperty.Create ("Command", typeof(ICommand), typeof(EventToCommandBehavior), null);
public static readonly BindableProperty CommandParameterProperty =
BindableProperty.Create ("CommandParameter", typeof(object), typeof(EventToCommandBehavior), null);
public static readonly BindableProperty InputConverterProperty =
BindableProperty.Create ("Converter", typeof(IValueConverter), typeof(EventToCommandBehavior), null);
public string EventName { ... }
public ICommand Command { ... }
public object CommandParameter { ... }
public IValueConverter Converter { ... }
...
}
当EventToCommandBehavior
类被使用时,Command
属性应该是数据绑定到一个ICommand
被执行以响应在EventName
属性中定义的事件触发。该行为会期望找到ICommand
在BindingContext
所连接的控制的。
默认情况下,事件的事件参数将传递给该命令。该数据可以通过绑定引擎在源和目标之间传递,可以通过将IValueConverter
实现指定为Converter
属性值来进行转换。或者,可以通过指定CommandParameter
属性值将参数传递给命令。
实现覆盖
的EventToCommandBehavior
类重写OnAttachedTo
和OnDetachingFrom
所述的方法BehaviorBase<T>
类,如在下面的代码例如:
public class EventToCommandBehavior : BehaviorBase<View>
{
...
protected override void OnAttachedTo (View bindable)
{
base.OnAttachedTo (bindable);
RegisterEvent (EventName);
}
protected override void OnDetachingFrom (View bindable)
{
DeregisterEvent (EventName);
base.OnDetachingFrom (bindable);
}
...
}
该OnAttachedTo
方法通过调用该方法执行设置RegisterEvent
,将该EventName
属性的值作为参数传递。该OnDetachingFrom
方法通过调用该方法执行清理DeregisterEvent
,将该EventName
属性的值作为参数传递。
实施行为功能
该行为的目的是执行由Command
属性定义的命令以响应由属性定义的事件触发EventName
。核心行为功能如下代码示例所示:
public class EventToCommandBehavior : BehaviorBase<View>
{
...
void RegisterEvent (string name)
{
if (string.IsNullOrWhiteSpace (name)) {
return;
}
EventInfo eventInfo = AssociatedObject.GetType ().GetRuntimeEvent (name);
if (eventInfo == null) {
throw new ArgumentException (string.Format ("EventToCommandBehavior: Can't register the '{0}' event.", EventName));
}
MethodInfo methodInfo = typeof(EventToCommandBehavior).GetTypeInfo ().GetDeclaredMethod ("OnEvent");
eventHandler = methodInfo.CreateDelegate (eventInfo.EventHandlerType, this);
eventInfo.AddEventHandler (AssociatedObject, eventHandler);
}
void OnEvent (object sender, object eventArgs)
{
if (Command == null) {
return;
}
object resolvedParameter;
if (CommandParameter != null) {
resolvedParameter = CommandParameter;
} else if (Converter != null) {
resolvedParameter = Converter.Convert (eventArgs, typeof(object), null, null);
} else {
resolvedParameter = eventArgs;
}
if (Command.CanExecute (resolvedParameter)) {
Command.Execute (resolvedParameter);
}
}
...
}
该RegisterEvent
方法是响应于EventToCommandBehavior
附加到控件而执行的,它接收EventName
属性的值作为参数。该方法然后尝试EventName
在附带的控件上定位属性中定义的事件。只要可以找到事件,该OnEvent
方法就被注册为事件的处理程序方法。
该OnEvent
方法是在EventName
属性中定义的事件触发时执行的。只要该Command
属性引用了一个有效ICommand
的方法,该方法会尝试检索一个参数传递给ICommand
如下:
- 如果
CommandParameter
属性定义了一个参数,则它将被检索。 - 否则,如果
Converter
属性定义了一个IValueConverter
实现,则转换器被执行,并且通过绑定引擎在事件源和目标之间传递的事件参数数据进行转换。 - 否则,假定事件参数为参数。
ICommand
然后执行数据绑定,将参数传递给命令,前提是该CanExecute
方法返回true
。
虽然这里未示出,但是EventToCommandBehavior
还包括DeregisterEvent
通过该OnDetachingFrom
方法执行的方法。该DeregisterEvent
方法用于定位和注销EventName
属性中定义的事件,以便清除任何潜在的内存泄漏。
消费行为
的EventToCommandBehavior
类可以被附连到Behaviors
一个控制集合,如下面的XAML代码示例表明:
<ListView ItemsSource="{Binding People}">
<ListView.Behaviors>
<local:EventToCommandBehavior EventName="ItemSelected" Command="{Binding OutputAgeCommand}"
Converter="{StaticResource SelectedItemConverter}" />
</ListView.Behaviors>
</ListView>
<Label Text="{Binding SelectedItemText}" />
等效的C#代码显示在以下代码示例中:
var listView = new ListView ();
listView.SetBinding (ItemsView<Cell>.ItemsSourceProperty, "People");
listView.Behaviors.Add (new EventToCommandBehavior {
EventName = "ItemSelected",
Command = ((HomePageViewModel)BindingContext).OutputAgeCommand,
Converter = new SelectedItemEventArgsToSelectedItemConverter ()
});
var selectedItemLabel = new Label ();
selectedItemLabel.SetBinding (Label.TextProperty, "SelectedItemText");
的Command
行为的属性是绑定到数据OutputAgeCommand
相关联的视图模型的属性,而Converter
属性被设置为SelectedItemConverter
实例,它返回SelectedItem
的ListView
来自SelectedItemChangedEventArgs
。
在运行时,行为将响应与控件的交互。当选择项目时ListView
,ItemSelected
事件将触发,这将OutputAgeCommand
在ViewModel中执行。反过来,这将更新绑定到的ViewModel SelectedItemText
属性Label
,如以下屏幕截图所示:
使用此行为在事件触发时执行命令的优点是,命令可以与未设计为与命令交互的控件相关联。此外,这将从代码隐藏文件中删除锅炉板事件处理代码。
概要
本文演示了使用Xamarin.Forms行为在事件触发时调用命令。行为可用于将命令与未设计为与命令交互的控件相关联。