我正在编写一个接收参数的 RelayCommand,但在调用实现该命令的方法时遇到问题。
我有以下 RelayCommand 类:
using System.Windows.Input;
namespace RCadastral.MVVM
{
public class RelayCommand : ICommand
{
private Action<object> execute;
private Func<object, bool> canExecute;
public event EventHandler? CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
{
this.execute = execute;
this.canExecute = canExecute;
}
public bool CanExecute(object? parameter)
{
return canExecute == null || canExecute(parameter);
}
public void Execute(object? parameter)
{
execute(parameter);
}
}
}
我认为我有以下几点:
<Window x:Class="RCadastral.View.DetalhePassoModalWindow"
x:Name="DetalhePassoMW"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:RCadastral.View">
<Button x:Name="Back"
Content="Voltar"
Command="{Binding CloseCommand}"
CommandParameter="{Binding ElementName=DetalhePassoMW}"/>
</Window>
在五月视图模式中我有以下内容:
public RelayCommand CloseCommand => new RelayCommand(execute => Close());
private void Close(Window window)
{
// Sime logic...
window.Close();
}
如何将参数传递给 Close() 方法?
我真的很困惑,没有任何效果。请帮忙。
所以基本上,你做的一切都是正确的。在这段代码中
public RelayCommand CloseCommand => new RelayCommand(execute => Close());
private void Close(Window window)
{
// Sime logic...
window.Close();
}
您从 XAML 中使用 Window
作为命令参数传递的
ElementName
对象将是您用作命令操作的匿名函数中的
execute
变量。所以你能做的就是将其转换为正确的类型,然后执行你的逻辑:
public RelayCommand CloseCommand => new RelayCommand(execute => Close(execute as Window));
但是您也可以采用我的 ICommand
接口实现,它允许您使用带有通用参数的命令和更方便的方式来编写代码。这是:
using System.Windows.Input;
namespace Wpf.Mvvm.Actions;
/// <summary>
/// Common <see cref="ICommand"/> implementation.
/// </summary>
/// <remarks>
/// Initializes a new instance of the <see cref="Command"/> class.
/// </remarks>
/// <param name="action">
/// Command action.
/// </param>
/// <param name="predicate">
/// Command predicate.
/// </param>
public sealed class Command(Action<object?> action, Func<object?, bool>? predicate) : ICommand
{
#region Fields
private readonly Func<object?, bool> _predicate = predicate ?? SuppressPredicate;
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="Command"/> class.
/// </summary>
/// <param name="action">
/// Command action.
/// </param>
/// <param name="predicate">
/// Command predicate.
/// </param>
public Command(Action<object?> action, Func<bool>? predicate)
: this(action, predicate is null ? null : p => predicate()) { }
/// <summary>
/// Initializes a new instance of the <see cref="Command"/> class.
/// </summary>
/// <param name="action">
/// Command action.
/// </param>
/// <param name="predicate">
/// Command predicate.
/// </param>
public Command(Action action, Func<object?, bool>? predicate)
: this(a => action(), predicate) { }
/// <summary>
/// Initializes a new instance of the <see cref="Command"/> class.
/// </summary>
/// <param name="action">
/// Command action.
/// </param>
/// <param name="predicate">
/// Command predicate.
/// </param>
public Command(Action action, Func<bool>? predicate)
: this(a => action(), predicate is null ? null : p => predicate()) { }
/// <summary>
/// Initializes a new instance of the <see cref="Command"/> class.
/// </summary>
/// <param name="action">
/// Command action.
/// </param>
public Command(Action<object?> action)
: this(action, null as Func<object?, bool>) { }
/// <summary>
/// Initializes a new instance of the <see cref="Command"/> class.
/// </summary>
/// <param name="action">
/// Command action.
/// </param>
public Command(Action action)
: this(a => action(), null as Func<object?, bool>) { }
#endregion
#region Public methods
/// <inheritdoc/>
public bool CanExecute(object? parameter)
=> _predicate(parameter);
/// <inheritdoc/>
public void Execute(object? parameter)
=> action(parameter);
#endregion
#region Private methods
/// <summary>
/// Predicate suppression.
/// <para>
/// Used when constructor input predicate is <see langword="null"/>.
/// </para>
/// </summary>
/// <param name="parameter">
/// Predicate parameter.
/// </param>
/// <returns>
/// Always returns <see langword="true"/>, meaning if
/// <see langword="null"/> was passed into the command constructor
/// - it will always be eligible for execution.
/// </returns>
private static bool SuppressPredicate(object? parameter)
=> true;
#endregion
#region Events
/// <inheritdoc/>
public event EventHandler? CanExecuteChanged
{
add => CommandManager.RequerySuggested += value;
remove => CommandManager.RequerySuggested -= value;
}
#endregion
}
/// <summary>
/// Parametrized <see cref="ICommand"/> implementation.
/// </summary>
public sealed class Command<T>(Action<T?> action, Func<T?, bool>? predicate) : ICommand
{
#region Fields
private readonly Func<T?, bool> _predicate = predicate ?? SuppressPredicate;
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="Command"/> class.
/// </summary>
/// <param name="action">
/// Command action.
/// </param>
/// <param name="predicate">
/// Command predicate.
/// </param>
public Command(Action<T?> action, Func<bool>? predicate)
: this(action, predicate is null ? null : p => predicate()) { }
/// <summary>
/// Initializes a new instance of the <see cref="Command"/> class.
/// </summary>
/// <param name="action">
/// Command action.
/// </param>
public Command(Action<T?> action)
: this(action, null as Func<T?, bool>) { }
#endregion
#region Public methods
/// <inheritdoc/>
public bool CanExecute(object? parameter)
=> _predicate((T?)parameter);
/// <inheritdoc/>
public void Execute(object? parameter)
=> action((T?)parameter);
#endregion
#region Private methods
/// <summary>
/// Predicate suppression.
/// <para>
/// Used when constructor input predicate is <see langword="null"/>.
/// </para>
/// </summary>
/// <param name="parameter">
/// Predicate parameter.
/// </param>
/// <returns>
/// Always returns <see langword="true"/>, meaning if
/// <see langword="null"/> was passed into the command constructor
/// - it will always be eligible for execution.
/// </returns>
private static bool SuppressPredicate(T? parameter)
=> true;
#endregion
#region Events
/// <inheritdoc/>
public event EventHandler? CanExecuteChanged
{
add => CommandManager.RequerySuggested += value;
remove => CommandManager.RequerySuggested -= value;
}
#endregion
}
因此,最终您的代码将如下所示:
public Command<Window> CloseCommand => new(Close);
private void Close(Window window)
{
// Some logic...
window.Close();
}
注意:我的代码利用了最新的 C# 功能之一 - 主构造函数,如果您使用的是较旧的语言版本,您可以手动恢复该用法。希望这有帮助!