如何识别单击哪个按钮?(MVVM)



继续沿着通往MVVM的路径,我来到了按钮命令。经过相当多的反复试验,我终于使用ICommandButton_Click命令进行了工作示例。

我的问题是,现在我已经进行了通用事件,我无法单击哪个按钮以对其应用一些逻辑。在我的示例中,我没有使用任何可以获取Sender信息的东西。通常在下面使用RoutedEventArgs

这样的东西
Button button = (Button)sender;

所以这就是我到目前为止所拥有的。

ICommand类:

public class CommandHandler : ICommand
{
    private Action _action;
    private bool _canExecute;
    public CommandHandler(Action action, bool canExecute)
    {
        _action = action;
        _canExecute = canExecute;
    }
    public bool CanExecute(object parameter)
    {
        return _canExecute;
    }
    public event EventHandler CanExecuteChanged;
    public void Execute(object parameter)
    {
        _action();
    }
}

和执行操作的代码:

private ICommand _clickCommand;
public ICommand ClickCommand => _clickCommand ?? (_clickCommand = new CommandHandler(MyAction, _canExecute));
public ViewModelBase()
{
    _canExecute = true;            
}
public void MyAction()
{
    //Apply logic here to differentiate each button
}

和xaml,

<Button Command="{Binding ClickCommand}" Style="{StaticResource RedButtonStyle}">MyButton</Button>

将同一命令绑定到其他按钮时,我将如何确定要单击的按钮?

you 可能不应该,但是如果您想要,则可以使用 CommandParameter=""

应该只使用2个ICommands。

xaml:

<Button Command="{Binding ClickCommandEvent}" CommandParameter="Jack"/>

ViewModel:

public RelayCommand ClickCommandEvent { get; set; }
public SomeClass()
{
    ClickCommandEvent = new RelayCommand(ClickExecute);
}
public void ClickExecute(object param)
{
    System.Diagnostics.Debug.WriteLine($"Clicked: {param as string}");
    string name = param as string;
    if (name == "Jack")
        HighFive();
}

,您的RelayCommand类是此锅炉板:

public class RelayCommand : ICommand
{
    #region Fields
    readonly Action<object> _execute;
    readonly Predicate<object> _canExecute;
    #endregion
    #region Constructors
    public RelayCommand(Action<object> execute) : this(execute, null) { }
    public RelayCommand(Action<object> execute, Predicate<object> canExecute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");
        _execute = execute;
        _canExecute = canExecute;
    }
    #endregion
    #region ICommand Members
    public bool CanExecute(object parameter)
    {
        return _canExecute == null ? true : _canExecute(parameter);
    }
    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }
    public void Execute(object parameter)
    {
        _execute(parameter);
    }
    #endregion
}

这将为您提供单击的Button

<Button Command="{Binding ClickCommand}" 
        CommandParameter="{Binding RelativeSource={RelativeSource Self}}"/>

您不应该将所有按钮绑定到同一命令。只需为每个按钮做一个不同的命令。

这是WPF依赖太多代码来实现简单操作的地方。我的意思是要处理按钮单击的30行代码有点荒谬,但是我们以某种方式说自己是"好"的事情,因为它会引起模式。

过多的代码是过多的代码。没有理由应该这么复杂。

有时,将多个命令引导到同一函数以重复使用相同的代码是不可避免的。我发现这种方法是确定单击哪些控件的最简单方法。在XAML中,我为这样的两个按钮设置了elementName:

      <Button Grid.Row="0"
              Grid.Column="0"
              Content="Read File"                  
              Command="{Binding ReadProButtonClick}"
              CommandParameter="{Binding ElementName=ReadFile}"/>          
      <Button Grid.Row="0"                  
              Grid.Column="1"
              Content="Batch Convert"                 
              Command="{Binding ReadProButtonClick}"
              CommandParameter="{Binding ElementName=BatchMode}"/>

然后在ViewModel中,我得到了这样的按钮的名称:

 Private void ReadProButton(Object context) {           
        Controls.Button btnClicked = CType(context, System.Windows.Controls.Button)           
        processName = btnClicked.Name
        ...
 }

因此,ProcessName将是batchmode或ReadFile取决于用户单击的内容。

最新更新