我已经使用MVVM-Light成功使用了一些自定义命令,但我希望我的应用程序能够响应标准的ApplicationCommands,而不仅仅是在Window级别,而是在详细的项目级别。
我有一个TreeView
我希望能够复制和粘贴节点。每个TreeViewItem都有自己的ViewModel,并且它们在XAML中通过HierarchicalDataTemplates
显示,因为有几种不同的类型。我已经在我的ViewModel类上实现了复制,粘贴以及CanCopy和CanPaste的方法。如果合适的话,我可以很容易地实现指向这些的MVVM-Light RelayCommands,但这似乎不对。
我想使用菜单,Ctrl + C和Ctrl + V或最终的上下文菜单来访问命令。我也不想破坏我的UI中其他元素的复制/粘贴功能,例如TextBoxes。为此目的使用内置的ApplicationCommands似乎是合适的。但是,我只看到在UserControl代码隐藏中处理这些示例。我没有(或者不需要)UserControl,也没有真正关注MVVM。
有没有办法可以将ApplicationCommand.Copy
和ApplicationCommand.Paste
命令绑定到我的ViewModel,即在数据模板中?
答案 0 :(得分: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>
答案 1 :(得分:3)
我相信您正在寻找CommandBindings
。我对某些文本框使用类似的东西:
<DataTemplate x:Key="textBoxTemplate" >
<TextBox>
<TextBox.CommandBindings>
<CommandBinding Command="ApplicationCommand.Copy"
Executed="CommandBinding_Executed"
CanExecute="CommandBinding_CanExecute">
</CommandBinding>
</TextBox.CommandBindings>
</TextBox>
</DataTemplate>
请注意,PreviewCanExecute
和PreviewExecuted
也可用。
编辑:查看示例here以使其符合MVVM。