How to bind ApplicationCommands to a ViewModel?

前端 未结 2 649
天命终不由人
天命终不由人 2020-12-09 05:21

I have successfully used a few custom commands using MVVM-Light, but I want my application to respond to the standard ApplicationCommands, not just at a Window level, but at

相关标签:
2条回答
  • 2020-12-09 05:55

    I believe that you are looking for CommandBindings. I use something similar for some textboxes:

        <DataTemplate x:Key="textBoxTemplate" >
            <TextBox>
                <TextBox.CommandBindings>
                    <CommandBinding Command="ApplicationCommand.Copy" 
                                    Executed="CommandBinding_Executed"
                                    CanExecute="CommandBinding_CanExecute">
                    </CommandBinding>
                </TextBox.CommandBindings>
            </TextBox>
        </DataTemplate>
    

    Note that PreviewCanExecute and PreviewExecuted are also available.

    Edit: Check out the sample here to make it MVVM compliant.

    0 讨论(0)
  • 2020-12-09 06:00

    I have resolved this using Behaviors attached to the TreeView. The TreeViewItems or Templates to not seem to get the commands routed to them. Fortunately, the TreeView also has a SelectedItem property that can be used to get the ViewModel!

    (Behaviors are conceptually similar to the solution in the link in @Natxo's answer, but it doesn't resolve everything.)

    The Behavior class:

    public class TreeViewClipboardBehavior : Behavior<TreeView>
    {
        protected override void OnAttached()
        {
            base.OnAttached();
    
            CommandBinding CopyCommandBinding = new CommandBinding(
                ApplicationCommands.Copy,
                CopyCommandExecuted,
                CopyCommandCanExecute);
            AssociatedObject.CommandBindings.Add(CopyCommandBinding);
    
            CommandBinding CutCommandBinding = new CommandBinding(
                ApplicationCommands.Cut,
                CutCommandExecuted,
                CutCommandCanExecute);
            AssociatedObject.CommandBindings.Add(CutCommandBinding);
    
            CommandBinding PasteCommandBinding = new CommandBinding(
                ApplicationCommands.Paste,
                PasteCommandExecuted,
                PasteCommandCanExecute);
            AssociatedObject.CommandBindings.Add(PasteCommandBinding);
        }
    
        private void CopyCommandExecuted(object target, ExecutedRoutedEventArgs e)
        {
            NestingItemTreeViewModelBase item = AssociatedObject.SelectedItem as NestingItemTreeViewModelBase;
            if (item != null && item.CanCopyToClipboard)
            {
                item.CopyToClipboard();
                e.Handled = true;
            }
        }
    
        private void CopyCommandCanExecute(object target, CanExecuteRoutedEventArgs e)
        {
            NestingItemTreeViewModelBase item = AssociatedObject.SelectedItem as NestingItemTreeViewModelBase;
            if (item != null)
            {
                e.CanExecute = item.CanCopyToClipboard;
                e.Handled = true;
            }
        }
    
        private void CutCommandExecuted(object target, ExecutedRoutedEventArgs e)
        {
            NestingItemTreeViewModelBase item = AssociatedObject.SelectedItem as NestingItemTreeViewModelBase;
            if (item != null && item.CanCutToClipboard)
            {
                item.CutToClipboard();
                e.Handled = true;
            }
        }
    
        private void CutCommandCanExecute(object target, CanExecuteRoutedEventArgs e)
        {
            NestingItemTreeViewModelBase item = AssociatedObject.SelectedItem as NestingItemTreeViewModelBase;
            if (item != null)
            {
                e.CanExecute = item.CanCutToClipboard;
                e.Handled = true;
            }
        }
    
    
        private void PasteCommandExecuted(object target, ExecutedRoutedEventArgs e)
        {
            NestingItemTreeViewModelBase item = AssociatedObject.SelectedItem as NestingItemTreeViewModelBase;
            if (item != null && item.CanPasteFromClipboard)
            {
                item.PasteFromClipboard();
                e.Handled = true;
            }
        }
    
        private void PasteCommandCanExecute(object target, CanExecuteRoutedEventArgs e)
        {
            NestingItemTreeViewModelBase item = AssociatedObject.SelectedItem as NestingItemTreeViewModelBase;
            if (item != null)
            {
                e.CanExecute = item.CanPasteFromClipboard;
                e.Handled = true;
            }
        }
    }
    

    The XAML

    <TreeView Grid.Row="2" ItemsSource="{Binding SystemTreeRoot}">
        <i:Interaction.Behaviors>
            <local:TreeViewClipboardBehavior/>
        </i:Interaction.Behaviors>
        <TreeView.Resources>
            <HierarchicalDataTemplate DataType="{x:Type local:MyViewModel}" ItemsSource="{Binding Children}">
                <!-- Template content -->
            </HierarchicalDataTemplate>
    </TreeView>
    
    0 讨论(0)
提交回复
热议问题