【问题标题】:detect which button was clicked from ViewModel WPF检测从 ViewModel WPF 中单击了哪个按钮
【发布时间】:2017-03-28 17:48:47
【问题描述】:

我的 WPF 应用程序的主窗口上有很多按钮。 这些按钮的命令应该具有相同的实现/功能,但根据按下哪个按钮,功能访问的文件/路径会发生变化。 如何在不使用按钮单击事件处理程序(Windows 窗体)的情况下检测从 ViewModel 中单击了哪个按钮?

这是RelayCommand类的实现:

public class RelayCommand : ICommand
{

    readonly Func<Boolean> _canExecute;
    readonly Action _execute;


    public RelayCommand(Action execute)
        : this(execute, null)
    {
    }

    public RelayCommand(Action execute, Func<Boolean> canExecute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");
        _execute = execute;
        _canExecute = canExecute;
    }


    public event EventHandler CanExecuteChanged
    {
        add
        {

            if (_canExecute != null)
                CommandManager.RequerySuggested += value;
        }

        remove
        {

            if (_canExecute != null)
                CommandManager.RequerySuggested -= value;
        }
    }


    public Boolean CanExecute(Object parameter)
    {
        return _canExecute == null ? true : _canExecute();
    }

    public void Execute(Object parameter)
    {
        _execute();
    }
}

ViewModel 中的命令代码如下:

void DoThisWorkExecute()
    {
        // if Button1 is clicked...do this

        // if Button2 is clicked...do this
    }

    bool CanDoThisWorkExecute()
    {
        return true;
    }

    public ICommand ButtonCommand { get { return new RelayCommand(DoThisWorkExecute, CanDoThisWorkExecute); } }

【问题讨论】:

  • 如何实例化按钮?常见的 MVVM 方式是在 XAML 中同时绑定 Command 和 CommandParameter,然后使用参数确定路径。
  • _execute_canExecute 字段的定义有点可疑(MVVM light?)。它应该是Action&lt;object&gt;Func&lt;object, bool&gt;。因此可以传递给 ICommand 方法的参数。

标签: c# wpf button mvvm


【解决方案1】:

您可以使用CommandParameter。类似的东西:

<Button Content="Open" Command="{Binding Path=ButtonCommand}" CommandParameter="Open"/>
<Button Content="Save" Command="{Binding Path=ButtonCommand}" CommandParameter="Save"/>

为此,您需要稍微不同的 RelayCommand 实现

/// <summary>
/// https://gist.github.com/schuster-rainer/2648922 
/// Implementation from Josh Smith of the RelayCommand
/// </summary>
public class RelayCommand : ICommand
{
    #region Fields

    readonly Predicate<object> _canExecute;
    readonly Action<object> _execute;
    #endregion // Fields

    #region Constructors

    /// <summary>
    /// Initializes a new instance of the <see cref="RelayCommand"/> class.
    /// </summary>
    /// <param name="execute">The execute.</param>
    public RelayCommand(Action<object> execute)
        : this(execute, null)
    {
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="RelayCommand"/> class.
    /// </summary>
    /// <param name="execute">The execute.</param>
    /// <param name="canExecute">The can execute.</param>
    /// <exception cref="System.ArgumentNullException">execute</exception>
    public RelayCommand(Action<object> execute, Predicate<object> canExecute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");

        _execute = execute;
        _canExecute = canExecute;
    }
    #endregion // Constructors

    #region ICommand Members


    /// <summary>
    /// Occurs when changes occur that affect whether or not the command should execute.
    /// </summary>
    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    /// <summary>
    /// Defines the method that determines whether the command can execute in its current state.
    /// </summary>
    /// <param name="parameter">Data used by the command.  If the command does not require data to be passed, this object can be set to null.</param>
    /// <returns>true if this command can be executed; otherwise, false.</returns>
    public bool CanExecute(object parameter)
    {
        return _canExecute == null ? true : _canExecute(parameter);
    }
    /// <summary>
    /// Defines the method to be called when the command is invoked.
    /// </summary>
    /// <param name="parameter">Data used by the command.  If the command does not require data to be passed, this object can be set to null.</param>
    public void Execute(object parameter)
    {
        _execute(parameter);
    }

    #endregion // ICommand Members
}

但是:我不会询问单击了哪个按钮,而是为每个单独的操作(例如打开、保存、退出)创建一个命令。重用命令(上下文菜单、KeyBindings、工具栏等)时,麻烦会少得多。您将始终必须提供 ui 元素。这确实打破了 MVVM 模式。为了充分利用RelayCommand 的强大功能,您真的必须摆脱旧的winforms 方法。

我自己写了一个sn-p代码,所以我不用写所有的代码。

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
    <CodeSnippet Format="1.0.0">
        <Header>
            <Title>RelayCommand</Title>
            <Shortcut>RelayCommand</Shortcut>
            <Description>Code snippet for usage of the Relay Command pattern</Description>
            <Author>Mat</Author>
            <SnippetTypes>
                <SnippetType>Expansion</SnippetType>
            </SnippetTypes>
        </Header>
        <Snippet>
            <Declarations>
                <Literal>
                    <ID>name</ID>
                    <ToolTip>Name of the command</ToolTip>
                    <Default>Save</Default>
                </Literal>
            </Declarations>
            <Code Language="csharp">
                <![CDATA[   private RelayCommand _$name$Command;
        public ICommand $name$Command
        {
            get
            {
                if (_$name$Command == null)
                {
                    _$name$Command = new RelayCommand(param => this.$name$(param),
                        param => this.Can$name$(param));
                }
                return _$name$Command;
            }
        }

        private bool Can$name$(object param)
        {
            return true;
        }

        private void $name$(object param)
        {
            MessageServiceHelper.RegisterMessage(new NotImplementedException());
        }]]>
            </Code>
        </Snippet>
    </CodeSnippet>
</CodeSnippets>

另见https://msdn.microsoft.com/en-us/library/z41h7fat.aspx

【讨论】:

    猜你喜欢
    • 2012-03-15
    • 1970-01-01
    • 2014-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-16
    相关资源
    最近更新 更多