【问题标题】:MVVM Call Command from CommandBinding来自 CommandBinding 的 MVVM 调用命令
【发布时间】:2015-09-04 20:13:15
【问题描述】:

我想将 CommandBinding 绑定到 ViewModel ICommand,这样,当用户点击 Delete 时,我可以触发 ViewModel 的删除逻辑。

我知道如何做到这一点的唯一方法是在后面的代码中:

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

任何 MVVM 方法可以实现相同的目标?

【问题讨论】:

    标签: wpf mvvm data-binding icommand


    【解决方案1】:

    这里是删除逻辑的一个例子:

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

    这里有一个注释:

    • delete Button 必须到达 ViewModel 的 DataContext,因此该语法让我们可以到达 Window 的 DataContext,这实际上正是我们想要的。

      • 对于CommandParameter,我们需要DataGrid 的SelectedItem,因此,使用RelativeSource 我们能够做到这一点。

    视图模型:

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

    我想就是这样,你现在有一个可行的例子。

    【讨论】:

    • 快速阅读您的代码,我不太确定这是否适合我....您更改了 CellsDataTemplate 并且我已经设置了它们,因为我有一些特别的需要适当视觉表示的数据类型(如 boolcheck_image
    • 对于我的特殊情况,我不需要 Command 参数,因为 SelectedItem 已经绑定到 ViewModel....但是你添加它很好,使它更完整。跨度>
    • 但是我的问题是关于 CommandBindings,所以当我按下 Del 键时,会调用一个命令......同样的情况也会发生在 CopyPaste 等......
    • 马特·汉密尔顿对此有一篇很好的文章:matthamilton.net/commandbindings-with-mvvm 但通常我使用上述方法..检查一下,它解释得很好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-10
    • 1970-01-01
    • 2012-04-21
    • 1970-01-01
    • 2016-01-11
    • 2021-08-30
    相关资源
    最近更新 更多