C# 使用MVVM将WPF命令绑定到DataItemTemplate

C# 使用MVVM将WPF命令绑定到DataItemTemplate,c#,wpf,mvvm,datatemplate,commandbinding,C#,Wpf,Mvvm,Datatemplate,Commandbinding,我正在从事一个WPF项目,我正在尝试遵循MVVM模式。过去我只使用DataTemplates来显示信息,但现在我想在我的模板上放置一个按钮,该按钮执行与包含单击按钮的项目相关的操作。我试图找出将代码绑定到按钮的最佳方法,使代码知道单击了哪个按钮 MyWindowViewModel包含通过命令属性公开的中继命令,以及“项”的ObservableCollection public class WindowViewModel { public ICommand ChangeItemComman

我正在从事一个WPF项目,我正在尝试遵循MVVM模式。过去我只使用DataTemplates来显示信息,但现在我想在我的模板上放置一个按钮,该按钮执行与包含单击按钮的项目相关的操作。我试图找出将代码绑定到按钮的最佳方法,使代码知道单击了哪个按钮

My
WindowViewModel
包含通过命令属性公开的中继命令,以及“项”的
ObservableCollection

public class WindowViewModel
{
    public ICommand ChangeItemCommand { get; private set; }

    public ObservableCollection<Item> Items {get;private set;}

    public WindowViewModel()
    {
        ChangeItemCommand = new RelayCommand(new Action<object>(this.ChangeItem));
        Items = new ObservableCollection<Item>();
    }

    public void ChangeItem(object o)
    {
        string key = (string)o;
        //do something to the item with provided key
    }
}
我的列表框数据模板如下所示

<DataTemplate DataType="local:ItemViewModel">
    <StackPanel Orientation="Horizontal">
        <Label Content="{Binding ItemName}"/>
            <Button Command="???" CommandParameter="{Binding ItemKey}"/>
         </StackPanel>
</DataTemplate>
或者,我可以使用
RelativeSource
直接绑定到
WindowViewModel.ChangeItemCommand
属性

<Button 
   Command="{Binding Path=ChangeItemCommand, 
                     RelativeSource={RelativeSource AncestorType={x:Type MyAppAWindow}}}" 
   CommandParameter="{Binding ItemKey}"/>

注意:我不完全确定我做得对


那么推荐哪种方法,或者还有其他更好的方法吗?

后者是首选方法


有几种方法,可以归结为偏好。与纯WPF CommandBindings相比,有很多MVVM框架类似,这使得绑定到命令更加容易。

这两个选项都很好,但真正要做的决定是,应该首先设计MVVM视图模型,然后视图应该正确使用它们

例如

  • 如果此操作是say removietem,那么我会说它属于
    WindowViewModel
    (因为这是关于更改
    WindowViewModel
    公开的集合)

  • 但是如果此操作是
    RefreshItemData
    ChangeItemDetails
    (例如
    ItemName
    ItemStatus
    ),则它属于
    ItemViewModel
    (因为此
    ItemViewModel
    可以在支持此操作的其他窗口中使用)

因此,我建议您首先考虑功能性、可重用性等因素设计ViewModels,然后使用合适的绑定功能(即
相对资源
元素名称
,direct等)

public class ItemViewModel
{
    public string ItemName { get; private set; }
    public string ItemKey { get; private set; }
    public ICommand ChangeItemCommand{ get; private set; }
}

<Button Command="{Binding ChangeItemCommand}" CommandParameter="{Binding ItemKey}"/>
<Button 
   Command="{Binding Path=ChangeItemCommand, 
                     RelativeSource={RelativeSource AncestorType={x:Type MyAppAWindow}}}" 
   CommandParameter="{Binding ItemKey}"/>