パラメータを使用してRelayCommandのインスタンスを動的に作成しようとしています。
public class RelayCommand<T> : ICommand
{
#region Declarations
private readonly Predicate<T> _canExecute;
private readonly Action<T> _execute;
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="RelayCommand<T>"/> class and the command can always be executed.
/// </summary>
/// <param name="execute">The execution logic.</param>
public RelayCommand(Action<T> execute)
: this(execute, null)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="RelayCommand<T>"/> class.
/// </summary>
/// <param name="execute">The execution logic.</param>
/// <param name="canExecute">The execution status logic.</param>
public RelayCommand(Action<T> execute, Predicate<T> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
複数のメソッドを持つViewModelがありますが、今は次のようにリストします。
public void MyMethod(object parameter);
public bool CanMyMethod(object parameter);
次のように、それらをRelayCommandのインスタンスに動的にフックしたいと思います。
ICommand command = new RelayCommand<ViewModel>((x)=>myviewmodel.MyMethod(myparameter),(x)=> myviewmodel.CanExecuteMyMethod(myparameter));
前の行は機能しますが、メソッド名は実行時に渡されるため、同じことを動的に実現する必要があります。
編集:いくつかの説明:私のシナリオでは、名前でメソッドを直接参照することはできません。RelayCommandの作成に使用するメソッド名は文字列として渡されます。
解決:
これが@ZafarYousafiの提案を使用した私の最終的な解決策です。メソッドパラメータ(オブジェクトmyparameter)のタイプであるため、RelayCommandおよびActionandPredicateにジェネリック'object'タイプを使用する方法に注意してください。
object myparameter = //Some value gets assigned here.
Delegate td1 = null, td2 = null;
MethodInfo method1 = myviewmodel.GetType().GetMethod("MyMethodNameAsString");
if (tmethod1 != null)
td1 = Delegate.CreateDelegate(typeof(Action<object>), myviewmodel, method1);
MethodInfo tmethod = viewmodel.GetType().GetMethod("Can" + "MyMethodNameAsString");
if (method2 != null)
d2 = Delegate.CreateDelegate(typeof(Predicate<object>), myviewmodel, method2);
if (d1 != null && d2 != null)
{
item.Command = new RelayCommand<object>(obj => ((Action<object>) td1)(myparameter), obj => ((Predicate<object>)td2)(myparameter));
}
これは次と同等である必要があります:
item.Command = new RelayCommand<object>(param=>myviewmodel.MyMethod(myparameter),param=>myviewmodel.CanMyMethod(myparameter));
重要な注意: @DanCが指摘したように、Josh Smithによって作成されたRelayCommandクラスは、作成時にパラメーターを受け取ることを目的としていません。適切に設計されたMVVMソリューションでは、RelayCommandパラメーターはCommandParameterプロパティのXAMLバインディングを介して渡されます。したがって、button.CommandがRelayCommandにバインドされている場合は、button.CommandParameterもバインドする必要があります。ここで説明するように:MVVMRelayCommandとパラメーター
古い失敗した試み: これは私がこれまでに持っているものです:
Delegate d1 = null, d2 = null;
MethodInfo method1 = myviewmodel.GetType().GetMethod("MyMethodNameAsString");
if (method1 != null)
d1 = Delegate.CreateDelegate(typeof(Action<ViewModel>), myviewmodel, method1);
MethodInfo method2 = myviewmodel.GetType().GetMethod("Can" + "MyMethodNameAsString");
if (method2 != null)
d2 = Delegate.CreateDelegate(typeof(Predicate<ViewModel>), myviewmodel, method2);
if (d1 != null && d2 != null)
{
item.Command = new RelayCommand<ViewModel>((Action<ViewModel>)d1, (Predicate<ViewModel>)d2);
}
これは正常に実行され、コンパイルエラーや実行時エラーは発生しませんが、RelayComandコンストラクターパラメーターを介してパラメーターを渡す方法がわかりません。
どんなアドバイスも大歓迎です、
ありがとう
私の前の質問に関連して