MVVM中如何通过CommandBinding调用命令

7

我想将一个CommandBinding绑定到一个ViewModel的ICommand,这样当用户按下Delete键时,我就可以触发ViewModel中的删除逻辑。

我知道的唯一方法是在代码后台使用以下代码:

    <UserControl.CommandBindings>
            <CommandBinding Command="ApplicationCommands.Delete" Executed="OnDeleteCommand" />
    </UserControl.CommandBindings>

有没有使用MVVM实现相同功能的方法?
1个回答

0
这是一个关于删除逻辑的示例:
<Window x:Class="DeleteCommandStack.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <DataGrid ItemsSource="{Binding items}" AutoGenerateColumns="False" CanUserAddRows="False">
        <DataGrid.Columns>
            <DataGridTemplateColumn>
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="{Binding Name}"/>
                            <Button Content="Delete" 
                                    Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=DataContext.deleteCommand}" 
                                    CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=SelectedItem}"/>
                        </StackPanel>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>
</Grid>

这里有一个注意点:

  • 删除按钮必须到达ViewModel的DataContext,因此语法让我们进入Window的DataContext,这实际上正是我们想要的。

    • 对于CommandParameter,我们需要DataGrid的SelectedItem,因此使用RelativeSource可以实现这一点。

ViewModel:

public class ViewModel
{
    public ObservableCollection<Model> items { get; set; }

    public ICommand deleteCommand { get; set; }

    public ViewModel()
    {
        items = new ObservableCollection<Model>();
        items.Add(new Model() { Name = "Name1" });
        items.Add(new Model() { Name = "Name2" });
        items.Add(new Model() { Name = "Name3" });
        items.Add(new Model() { Name = "Name4" });

        deleteCommand = new DeleteCommand(this);
    }

    public void DeleteHandler(object parameter)
    {
        items.Remove(parameter as Model);
    }
}

模型:

public class Model : INotifyPropertyChanged
{
    private string _Name;

    public string Name
    {
        get { return _Name; }
        set
        {
            _Name = value;
            PropertyChanged(this, new PropertyChangedEventArgs("Name"));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged = delegate { };
}

删除命令:

public class DeleteCommand : ICommand
{
    private ViewModel _vm;
    public DeleteCommand(ViewModel vm)
    {
        _vm = vm;
    }

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        _vm.DeleteHandler(parameter);
    }
}

还有设置DataContext的代码后台:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = new ViewModel();
    }
}

通过将ViewModel引用发送到DeleteCommand,我们能够调用并向其方法发送参数。
我们可以选择直接从命令中删除该项:
public void Execute(object parameter)
{
   _vm.items.Remove(parameter as Model);
}

我认为就是这样了,你现在有一个可用的示例。


快速阅读您的代码后,我不确定这对我是否有效......您更改了“Cells”的“DataTemplate”,而我已经设置了它们,因为我有一些需要适当视觉表示的特殊数据类型(例如将“bool”转换为“check_image”)。 - Michel Feinstein
对于我的特殊情况,我不需要一个 Command 参数,因为“SelectedItem”已经绑定到 ViewModel......但你添加它是很好的,这样会使它更完整。 - Michel Feinstein
但是我的问题是关于CommandBindings的,所以当我按下“Del”键时,会调用一个命令...同样的事情也会发生在“Copy”,“Paste”等操作中... - Michel Feinstein
Matt Hamilton在这方面有一篇好文章:http://matthamilton.net/commandbindings-with-mvvm,但通常我会使用上述方法...看看吧,解释得很清楚。 - Olaru Mircea

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接