CallMethodAction
源代码
CallMethodAction.cs这是一个相当简单易用的动作,它允许我们在事件触发器中调用一个方法。这个方法可以是任意一个对象的方法,比如 Window 的 Close,或视图模型(ViewModel)中的方法(但通常不推荐这样,而是建议使用 InvokeCommandAction 来绑定 VM 上的命令)。
比如我们希望在点击一个按钮后,关闭当前窗口。那么可以这样实现:
<Window ElementName="window"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors">
<Button Content="Close" Width="100" Height="30">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:CallMethodAction MethodName="Close" TargetObject="{Binding ElementName=window}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</Window>值得注意的是,内置的 CallMethodAction 只能调用无参数的方法。如果希望调用有参数的方法,并且支持传递参数,那么需要自定义一个 Action。这里有一个简单的实现:
using System.Windows;
using Microsoft.Xaml.Behaviors;
public class CallMethodAction : TriggerAction<DependencyObject>
{
public static readonly DependencyProperty TargetObjectProperty = DependencyProperty.Register(
nameof(TargetObject),
typeof(object),
typeof(CallMethodAction),
new PropertyMetadata(null)
);
public static readonly DependencyProperty MethodNameProperty = DependencyProperty.Register(
nameof(MethodName),
typeof(string),
typeof(CallMethodAction),
new PropertyMetadata(null)
);
public static readonly DependencyProperty ParameterProperty = DependencyProperty.Register(
nameof(Parameter),
typeof(object),
typeof(CallMethodAction),
new PropertyMetadata(null)
);
public object? TargetObject
{
get => GetValue(TargetObjectProperty);
set => SetValue(TargetObjectProperty, value);
}
public string? MethodName
{
get => (string?)GetValue(MethodNameProperty);
set => SetValue(MethodNameProperty, value);
}
public object? Parameter
{
get => GetValue(ParameterProperty);
set => SetValue(ParameterProperty, value);
}
protected override void Invoke(object parameter)
{
var target = TargetObject ?? AssociatedObject;
if (target == null || string.IsNullOrEmpty(MethodName))
return;
var type = target.GetType();
var method =
type.GetMethod(MethodName, new[] { Parameter?.GetType() ?? typeof(object) })
?? type.GetMethod(MethodName, new[] { typeof(object) })
?? type.GetMethod(MethodName, Type.EmptyTypes);
if (method == null)
return;
var parameters = method.GetParameters();
if (parameters.Length == 0)
{
method.Invoke(target, null);
}
else if (parameters.Length == 1)
{
method.Invoke(target, new[] { Parameter });
}
}
}这个自定义的 CallMethodAction 支持传递一个参数给目标方法(方法的入参类型必须为 object)。
此外,一些对于原生行为库的扩展的第三方库也提供了类似的实现,比如:
Livet - LivetCallMethodAction
Livet 提供的支持传参的方法,但还依赖了诸如 MethodBinder 等类型