在表达式主体成员中传递参数

问题描述 投票:0回答:1

我正在编写一个接收参数的 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() 方法?

我真的很困惑,没有任何效果。请帮忙。

c# wpf relaycommand
1个回答
0
投票

所以基本上,你做的一切都是正确的。在这段代码中

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# 功能之一 - 主构造函数,如果您使用的是较旧的语言版本,您可以手动恢复该用法。

希望这有帮助!

© www.soinside.com 2019 - 2024. All rights reserved.