【问题标题】:Pass selected item as command parameter vs. using a bound ViewModel Object (MVVM)将所选项目作为命令参数传递与使用绑定的 ViewModel 对象 (MVVM)
【发布时间】:2025-12-30 12:20:08
【问题描述】:

希望这是一个简单的 MVVM 问题,但我正在尝试掌握命令参数。

我让用户从 ListBox 中选择一个项目,然后单击“删除选定项”。 ListBox 将 SelectedItem 绑定到“SelectedTemplate”。我的按钮 XAML 如下所示:

<Button CommandParameter="{Binding SelectedTemplate}" Command="{Binding DeleteTemplateCommand}" Content="Delete Selected"/>

当我得到执行命令时,我正在从命令中读取参数。但是,我也可以访问“SelectedTemplate”。如果我使用传递的参数,那么我必须在删除对象之前将其转换为正确的对象类型,而不是继续删除“selectedTemplate”

public void DeleteTemplate(object template)
{
    Convert.ChangeType(template, typeof(Template));
    if (template == SelectedTemplate )
    {
        _ESTContext.Templates.Remove(SelectedTemplate);
    }     
}

我的问题是,在我看来,它似乎都满足 MVVM 理念,使用其中一种是否有好处/坏处?

【问题讨论】:

    标签: c# wpf mvvm relaycommand


    【解决方案1】:

    唯一真正的区别是可读性(并且可能需要引擎评估一个额外的绑定,但在这种情况下不会真正伤害到您)。

    无论哪种方式,您都在使用SelectedTemplate,所以我不会费心将它绑定到参数并直接使用它。

    除非这是您唯一使用 SelectedTemplate 的东西,在这种情况下,我会将它作为变量扔掉,并直接绑定到选择:

    <Button CommandParameter="{Binding ElementName=MyListBox, Path=SelectedItem}" Command="{Binding DeleteTemplateCommand}" Content="Delete Selected"/>
    

    【讨论】:

      【解决方案2】:

      使用命令参数的主要好处是您可以针对不同的输入执行相同的命令,而不是针对一个硬编码输入。能够删除任何项目可以说比仅删除SelectedTemplate 更灵活。在实践中,我倾向于使用参数。

      您可以通过使用通用命令实现(例如,RelayCommand&lt;TParameter&gt;)来避免“执行”回调中的强制转换。

      【讨论】:

      • 嗯。那是个很好的观点。但是,我仍然必须使用 GetType() 参数才能从正确的模型中正确删除它,对吗?
      • 通用RelayCommand&lt;T&gt; 将接受具有预期参数类型的回调(无论T 的类型是什么),并应在调用回调之前将参数转换为该类型。所以,不,您不需要自己进行任何转换。
      • 我得去研究如何实现回调...谢谢
      • 迈克,我想我现在有点迷失了......我有 public RelayCommand DeleteTemplateCommand { get { if (_deletetemplatecommand == null) { _deletetemplatecommand = new RelayCommand (删除模板,p=> 真); } 返回 _deletetemplate 命令; } } 但它仍然是“对象”类型。我正在删除“模型”或“模板”对象 - 如何将命令类型设置为正确的对象?
      • 回到原来的实现,将RelayCommand替换为RelayCommand&lt;Template&gt;,并将DeleteTemplate()中的参数从object更改为Template
      【解决方案3】:

      我的问题是,对我来说,它似乎都满足 MVVM 哲学,使用一个或另一个有好处/坏处吗?

      @MikeStrobel 为您提供了使用参数的一个很好的论据,所以我想您需要有人为使用 VM 属性进行争论!

      你是正确的,因为两者都满足 MVVM,所以实际上它只是归结为你希望你的应用程序如何工作。

      在我们具有此类功能的应用程序中,我们的SelectedTemplate 概念是 UI 工作方式的关键。将有NullToVisibility/Booleanconverters 绑定到该属性,指示某些控件是启用还是可见。无论您是否选择了一个东西,详细信息部分、命令按钮和各种其他工作流程都会挂起。考虑到这个工作流程,拥有一个有效的SelectedTemplate 将使DeleteTemplate 按钮处于活动状态。所以对我们来说,我们的命令,例如DeleteTemplateCommand 都将在SelectedTemplate 对象上运行是有意义的。这意味着我们不需要传递命令参数。

      对我们来说,对不是SelectedTemplate 的东西执行操作(例如删除)是没有意义的。对于您的应用程序和 UI,它可能会。

      【讨论】: