鉴于以下内容:
en_GB
有没有办法可以将GBP1.12
作为参数传递给方法调用£1.12
?
答案 0 :(得分:2)
CallMethodAction
只能用于调用不带参数的方法或带有两个参数的方法,其中第一个参数是object类型,第二个参数可以赋值给EventArgs类型的变量。
鉴于此,您将无法使用CallMethodAction
执行所需操作。但是,您可以创建自己的触发器操作,该操作将调用您的方法并传入您指定的值。我对此只进行了一些轻量级测试,但它应该非常接近你所需要的。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Windows;
using System.Windows.Interactivity;
namespace LocalActions
{
public class CallUnaryMethodAction : TargetedTriggerAction<DependencyObject>
{
// The name of the method to invoke.
public static readonly DependencyProperty MethodNameProperty =
DependencyProperty.Register( "MethodName",
typeof( string ),
typeof( CallUnaryMethodAction ),
new PropertyMetadata( OnNeedsMethodInfoUpdated ) );
public string MethodName
{
get { return (string)GetValue( MethodNameProperty ); }
set { SetValue( MethodNameProperty, value ); }
}
// Flag that lets us determine if we want to search non-public methods in our target object.
public static readonly DependencyProperty AllowNonPublicMethodsProperty =
DependencyProperty.Register( "AllowNonPublicMethods",
typeof( bool ),
typeof( CallUnaryMethodAction ),
new PropertyMetadata( OnNeedsMethodInfoUpdated ) );
public bool AllowNonPublicMethods
{
get { return (bool)GetValue( AllowNonPublicMethodsProperty ); }
set { SetValue( AllowNonPublicMethodsProperty, value ); }
}
// Parameter we want to pass to our method. If this has not been set, then the value passed
// to the trigger action's Invoke method will be used instead.
public static readonly DependencyProperty ParameterProperty =
DependencyProperty.Register( "Parameter",
typeof( object ),
typeof( CallUnaryMethodAction ) );
public object Parameter
{
get { return GetValue( ParameterProperty ); }
set { SetValue( ParameterProperty, value ); }
}
private static void OnNeedsMethodInfoUpdated( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
var action = d as CallUnaryMethodAction;
if( action != null )
action.UpdateMethodInfo();
}
protected override void OnAttached()
{
UpdateMethodInfo();
}
protected override void OnTargetChanged( DependencyObject oldTarget, DependencyObject newTarget )
{
UpdateMethodInfo();
}
protected override void Invoke( object parameter )
{
object target = this.TargetObject ?? this.AssociatedObject;
if( target == null )
return;
// Determine what we are going to pass to our method.
object methodParam = ReadLocalValue( ParameterProperty ) == DependencyProperty.UnsetValue ?
parameter : this.Parameter;
// Pick the best method to call given the parameter we want to pass.
Method methodToCall = m_methods.FirstOrDefault( method =>
(methodParam != null) && method.ParameterInfo.ParameterType.IsAssignableFrom( methodParam.GetType() ) );
if( methodToCall == null )
throw new InvalidOperationException( "No suitable method found." );
methodToCall.MethodInfo.Invoke( target, new object[] { methodParam } );
}
private void UpdateMethodInfo()
{
m_methods.Clear();
object target = this.TargetObject ?? this.AssociatedObject;
if( target == null || string.IsNullOrEmpty( this.MethodName ) )
return;
// Find all unary methods with the given name.
BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
if( this.AllowNonPublicMethods )
flags |= BindingFlags.NonPublic;
foreach( MethodInfo methodInfo in target.GetType().GetMethods( flags ) )
{
if( methodInfo.Name == this.MethodName )
{
ParameterInfo[] parameters = methodInfo.GetParameters();
if( parameters.Length == 1 )
m_methods.Add( new Method( methodInfo, parameters[0] ) );
}
}
// Order the methods so that methods with most derived parameters are ordered first.
// This will help us pick the most appropriate method in the call to Invoke.
m_methods = m_methods.OrderByDescending<Method, int>( method =>
{
int rank = 0;
for( Type type = method.ParameterInfo.ParameterType; type != typeof( object ); type = type.BaseType )
++rank;
return rank;
} ).ToList<Method>();
}
private List<Method> m_methods = new List<Method>();
// Holds info on the list of possible methods we can call.
private class Method
{
public Method( MethodInfo methodInfo, ParameterInfo paramInfo )
{
this.MethodInfo = methodInfo;
this.ParameterInfo = paramInfo;
}
public MethodInfo MethodInfo { get; private set; }
public ParameterInfo ParameterInfo { get; private set; }
}
}
}
然后,您可以像在CallMethodAction
中一样在XAML中使用它。您只需要引入适当的XAML命名空间。
...
xmlns:local="clr-namespace:LocalActions"
...
<ei:DataTrigger
Binding="{
Binding SomeVar,
ElementName=SomeElement,
FallbackValue=False,
Mode=OneWay}"
Value="True">
<local:CallUnaryMethodAction
TargetObject="{
Binding Mode=OneWay,
Path=Children,
Source={StaticResource Foo}}"
MethodName="Add"
Parameter="{StaticResource Bar}"/>
</ei:DataTrigger>
假设您的DoubleAnimationUsingKeyFrames
确实是一种资源(我根据您对x:Key
的使用而猜测)。如果这不合适,那么您需要根据需要调整绑定。
答案 1 :(得分:1)
您可以尝试使用Interactivity中的 InvokeCommandAction
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
<ei:DataTrigger
Binding="{
Binding SomeVar,
ElementName=SomeElement,
FallbackValue=False,
Mode=OneWay}"
Value="True">
<i:InvokeCommandAction Command="{Binding SomeCommand, Source={StaticResource SomeViewModel}}" CommandParameter="Bar"/>
</ei:DataTrigger>