动态地将参数分配给MVVM Light中的RelayCommand

时间:2016-07-08 12:54:44

标签: c# wpf mvvm mvvm-light relaycommand

我已经看到了很多使用MVVM Light中的RelayCommand类通过命令传递参数的例子,但是我想要的和我看到的之间有一点点差异。

我想创建一些按钮,其中所有按钮都与ModuleType相关联。当他们的行动被执行时,我想知道它是哪个ModuleType。我想以一种代码有效的方式做到这一点,所以不必手动创建RelayCommands,而是在foreach循环中完成所有操作,也因为我不知道我必须在开始时创建多少个按钮。

所以这是代码。在我的 ViewModel

public ModuleSelectionViewModel(MachineStatusModel model, int order, List<ModuleType> modules) : base(model)
{
    ........

    // create button for each of the modules
    foreach (ModuleType mod in modules)
    {
        _navBarButtons.Add(new NavButton(mod.ToString(), new RelayCommand<ModuleType>(exec => ButtonExecute(mod)), mod));
    }

    RaisePropertyChanged("NavBarButtons");
}


// Binding to the Model
public ObservableCollection<NavButton> NavBarButtons
{
    get { return _navBarButtons; }
}


// Execut Action
public void ButtonExecute(ModuleType mod)
{
    WriteToLog("Selected " + mod.ToString());
}


// Support class
public class NavButton
{
    public string ButtonContent { get; set; }
    public ICommand ButtonCommand { get; set; }
    public ModuleType ButtonModuleType;

    public NavButton(string content, ICommand relay, ModuleType moduleType)
    {
        this.ButtonContent = content;
        this.ButtonCommand = relay;
        this.ButtonModuleType = moduleType;
    }
}

我还在学习lambda表达式,所以我想我在RelayCommand的初始化上做错了。

2 个答案:

答案 0 :(得分:2)

如果你执行10,10,10,10,10,10,10,10,10,10循环并在lambda表达式中使用循环变量,则会捕获它。不幸的是,变量的范围不正确(至少在旧版本的C#中,changes with C# 5(谢谢,Mafii))。

所以你需要做一些事情:

foreach

答案 1 :(得分:0)

关于解决方案H.B.发布:不确定为什么它不能处理lambda函数,为什么ButtonExecute在按下按钮时没有被执行。而且我也不理解定义像'foo =&gt;这样的lambda函数的逻辑。当foo为空并传递给函数时,ButtonExecute(foo)'。但无论如何......

这就是我所做的并且正在发挥作用:

<强>模型

<ItemsControl Name="NavButtonsItemsControl" ItemsSource="{Binding NavBarButtons}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button Content="{Binding ButtonContent}" CommandParameter="{Binding ButtonModuleType}" Command="{Binding ButtonCommand}"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>

</ItemsControl>

ViewModel (检查我最初问题中的其余代码)

.........

_navBarButtons.Add(new NavButton(mod.ToString(), new RelayCommand<ModuleType>(ButtonExecute), type));

.........

private void ButtonExecute(ModuleType state)
{
    WriteToLog("Command with parameter " + state.ToString());
}

您可以使用Object而不是ModuleType使其更通用。而不是使用lambda函数的解决方案是在按钮中定义CommandParameter绑定并将该值作为execute函数中的参数。我不认为绑定是明确定义的,这就是为什么我很难理解值是如何达到'ButtonExecute'的原因,但是遵循Dominik Schmidt tutorial中的步骤它有效。