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

时间:2009-05-01 04:37:06

标签: .net wpf data-binding mvvm lambda

我想通过使用RelayCommand将我的应用程序的XAML(View)中定义的参数传递给ViewModel类。我跟着Josh Smith's excellent article on MVVM并实施了以下内容。

XAML代码

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

ViewModel代码

  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

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

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

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

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

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

有办法做到这一点吗?

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

6 个答案:

答案 0 :(得分:28)

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

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

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

答案 1 :(得分:13)

你会将lambda中的param传递给命令,如下所示:

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

答案 2 :(得分:6)

之前没有任何内容发布在我身上。

事实证明,<object>之后的所有答案都缺少RelayCommand

这对我有用:

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;
}

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

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

private bool OkCommand_CanExecute(object obj) { }

答案 3 :(得分:2)

我只是想卖掉我的观点,看看这是否有效......

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

答案 4 :(得分:2)

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

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

public object ParameterValue
{
  get;
  set;
}

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

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

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

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

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

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

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

答案 5 :(得分:1)

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