.net 使用 ViewModel 中定义的 RelayCommand 传递参数(来自 Josh Smith 示例)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/810208/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 12:37:01  来源:igfitidea点击:

Passing a parameter using RelayCommand defined in the ViewModel (from Josh Smith example)

.netwpfdata-bindingmvvmlambda

提问by eesh

I would like to pass a parameter defined in the XAML (View) of my application to the ViewModel class by using the RelayCommand. I followed Josh Smith's excellent article on MVVMand have implemented the following.

我想使用 RelayCommand 将我的应用程序的 XAML(视图)中定义的参数传递给 ViewModel 类。我关注了Josh Smith 关于 MVVM 的优秀文章,并实现了以下内容。

XAML Code

XAML 代码

        <Button 
        Command="{Binding Path=ACommandWithAParameter}"
        CommandParameter="Orange"
        HorizontalAlignment="Left" 
        Style="{DynamicResource SimpleButton}" 
        VerticalAlignment="Top" 
        Content="Button"/>

ViewModel Code

视图模型代码

  public RelayCommand _aCommandWithAParameter;
  /// <summary>
  /// Returns a command with a parameter
  /// </summary>
  public RelayCommand ACommandWithAParameter
  {
     get
     {
        if (_aCommandWithAParameter == null)
        {
           _aCommandWithAParameter = new RelayCommand(
               param => this.CommandWithAParameter("Apple")
               );
        }

        return _aCommandWithAParameter;
     }
  }

  public void CommandWithAParameter(String aParameter)
  {
     String theParameter = aParameter;
  }
  #endregion

I set a breakpoint in the CommandWithAParameter method and observed that aParameter was set to "Apple", and not "Orange". This seems obvious as the method CommandWithAParameter is being called with the literal String "Apple".

我在 CommandWithAParameter 方法中设置了一个断点,并观察到 ​​aParameter 设置为“Apple”,而不是“Orange”。这似乎很明显,因为使用文字字符串“Apple”调用方法 CommandWithAParameter。

However, looking up the execution stack, I can see that "Orange", the CommandParameter I set in the XAML is the parameter value for RelayCommand implemenation of the ICommand Execute interface method.

但是,查找执行堆栈,可以看到“Orange”,我在XAML 中设置的CommandParameter 是ICommand Execute 接口方法的RelayCommand 实现的参数值。

That is the value of parameter in the method below of the execution stack is "Orange",

即执行堆栈下面方法中的参数值为“Orange”,

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

What I am trying to figure out is how to create the RelayCommand ACommandWithAParameter property such that it can call the CommandWithAParameter method with the CommandParameter "Orange" defined in the XAML.

我想弄清楚的是如何创建 RelayCommand ACommandWithAParameter 属性,以便它可以使用 XAML 中定义的 CommandParameter“Orange”调用 CommandWithAParameter 方法。

Is there a way to do this?

有没有办法做到这一点?

Why do I want to do this? Part of "On The Fly Localization" In my particular implementation I want to create a SetLanguage RelayCommand that can be bound to multiple buttons. I would like to pass the two character language identifier ("en", "es", "ja", etc) as the CommandParameter and have that be defined for each "set language" button defined in the XAML. I want to avoid having to create a SetLanguageToXXX command for each language supporting and hard coding the two character language identifier into each RelayCommand in the ViewModel.

我为什么要这样做?“即时本地化”的一部分 在我的特定实现中,我想创建一个可以绑定到多个按钮的 SetLanguage RelayCommand。我想将两个字符的语言标识符(“en”、“es”、“ja”等)作为 CommandParameter 传递,并为 XAML 中定义的每个“设置语言”按钮定义它。我想避免必须为每种语言创建一个 SetLanguageToXXX 命令,支持并将两个字符语言标识符硬编码到 ViewModel 中的每个 RelayCommand 中。

回答by Kent Boogaart

I don't understand why you have the extra complexity of specifying the lambda in the first place. Why not just do this:

我不明白为什么你首先要指定 lambda 的额外复杂性。为什么不这样做:

if (_aCommandWithAParameter == null)
{           
    _aCommandWithAParameter = new RelayCommand<object>(CommandWithAParameter);
}

private void CommandWithAParameter(object state)
{
    var str = state as string;
}

回答by Paul Alexander

You'll pass the param in the lambda to the command like so:

您将把 lambda 中的参数传递给命令,如下所示:

if (_aCommandWithAParameter == null)
{           
    _aCommandWithAParameter = new RelayCommand(               
        param => this.CommandWithAParameter(param)
        );        
}

回答by JCH2k

Nothing posted here before worked for me.

在对我来说有效之前,这里没有发布任何内容。

Turns out, all answers are missing the <object>after RelayCommand!

事实证明,所有答案都在<object>之后丢失了RelayCommand

This works for me:

这对我有用:

public RelayCommand<object> OKCommand
{
    get
    {
        if (_okCommand == null)
            _okCommand = new RelayCommand<object>(OkCommand_Execute);
        return _okCommand;
    }
}
private RelayCommand<object> _okCommand = null;

private void OkCommand_Execute(object obj)
{
    Result = true;
}

If you want to use aCanExecutemethod, use the following code:

如果要使用CanExecute方法,请使用以下代码:

_okCommand = new RelayCommand<object>(OkCommand_Execute, OkCommand_CanExecute);

private bool OkCommand_CanExecute(object obj) { }

回答by Emmanuel Romulus

Here is a simple solution for the commandparameter as I was looking for help on the subject. I could not find anything online that was simple enough. The following solution works well when you are using a relaycommand. I had a few hyperlinks for which I needed to get the url value that was clicked using the command parameter.

这是 commandparameter 的一个简单解决方案,因为我正在寻找有关该主题的帮助。我在网上找不到任何足够简单的东西。当您使用中继命令时,以下解决方案很有效。我有几个超链接需要获取使用命令参数单击的 url 值。

Step 1: In your relay command, create a simple property that will hold the parameter object value. You could call it parametervalue or any name that you prefer.

步骤 1:在您的中继命令中,创建一个将保存参数对象值的简单属性。您可以将其称为参数值或您喜欢的任何名称。

public object ParameterValue
{
  get;
  set;
}

Step 2: In the Execute Method of the RelayCommand class, set the value or the property created above to the parameter from the Execute method.

第二步:在RelayCommand类的Execute Method中,将上面创建的值或属性设置为Execute方法中的参数。

readonly Action<object> m_execute;       // Action to execute

public void Execute(object parameter)
 {
   this.ParameterValue = parameter;
   m_execute(parameter);
 }

Step 3: Now when you can bind the CommandParameter in xaml to any value you want to retrieve when the command is executed. example:

第 3 步:现在可以将 xaml 中的 CommandParameter 绑定到执行命令时要检索的任何值。例子:

<TextBlock>
  <Hyperlink Command="{Binding Path=NavigateUrlCmd}"
             CommandParameter="{Binding ElementName=tbwebsite, Path=Text}">
    <TextBlock Name="tbwebsite" Text="{Binding Path=website}"/>
  </Hyperlink>
</TextBlock> 

If you have a command called chickenCommand, when executed you could access the parameter: chickenCommand.ParameterValue

如果您有一个名为chickenCommand 的命令,则在执行时您可以访问参数:chickenCommand.ParameterValue

I hope this helps somebody. Thank you for all your previous help.

我希望这对某人有帮助。感谢您之前的所有帮助。

回答by Vishu

I am just trying to sell my point, check this out whether this works...

我只是想推销我的观点,看看这是否有效......

http://mywpf-visu.blogspot.com/2009/12/relay-command-how-to-pass-parameter.html

http://mywpf-visu.blogspot.com/2009/12/relay-command-how-to-pass-parameter.html

回答by Rick O'Shea

I cannot substitute a reference to the method name for the lamda expression withing a compile error. Apparently, and by no means surprisingly, a non-static method name reference cannot be used in place of a lambda. I hardly see it as "added complexity". Consistently passing lamdas makes sense to me.

我无法用编译错误替换对 lamda 表达式的方法名称的引用。显然,并且毫不奇怪,不能使用非静态方法名称引用来代替 lambda。我几乎不认为它是“增加的复杂性”。持续传递 lamdas 对我来说很有意义。