12

我已经成功地使用了一些使用 MVVM-Light 的自定义命令,但我希望我的应用程序能够响应标准的 ApplicationCommands,不仅在窗口级别,而且在详细的项目级别。

我有一个TreeView我希望能够复制和粘贴节点的节点。每个 TreeViewItem 都有自己的 ViewModel,它们通过HierarchicalDataTemplatesXAML 显示,因为有几种不同的类型。我已经在我的 ViewModel 类上实现了复制、粘贴以及 CanCopy 和 CanPaste 的方法。如果合适的话,我可以很容易地实现指向这些的 MVVM-Light RelayCommands,但这似乎不对。

我想使用菜单、Ctrl+C 和 Ctrl+V 或最终使用上下文菜单来访问命令。我也不想破坏 UI 中其他元素的复制/粘贴功能,例如 TextBox。为此目的使用内置的 ApplicationCommands 似乎是合适的。但是,我只看到在 UserControl 代码隐藏中处理这些示例。我没有(或以其他方式需要)UserControl,也不是真正遵循 MVVM。

有没有一种方法可以将命令绑定ApplicationCommand.CopyApplicationCommand.Paste我的 ViewModel,即在数据模板中?

4

2 回答 2

9

我已经使用附加到 TreeView 的行为解决了这个问题。TreeViewItems 或模板似乎没有将命令路由到它们。幸运的是,TreeView 还有一个 SelectedItem 属性,可以用来获取 ViewModel!

(行为在概念上类似于@Natxo 答案中链接中的解决方案,但它并不能解决所有问题。)

行为类:

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

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>
于 2011-10-12T18:59:47.160 回答
3

我相信你正在寻找CommandBindings。我对一些文本框使用了类似的东西:

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

请注意PreviewCanExecutePreviewExecuted也可用。

编辑:在此处查看示例以使其符合 MVVM。

于 2011-10-04T09:58:18.380 回答