如何将 ApplicationCommands 绑定到 ViewModel? [英] How to bind ApplicationCommands to a ViewModel?
问题描述
我已经使用 MVVM-Light 成功地使用了一些自定义命令,但我希望我的应用程序响应标准 ApplicationCommands,不仅在窗口级别,而且在详细的项目级别.
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 a detailed item level as well.
我有一个 TreeView
,我希望能够在其中复制和粘贴节点.每个 TreeViewItem 都有自己的 ViewModel,它们通过 XAML 中的 HierarchicalDataTemplates
显示为有几种不同的类型.我已经在我的 ViewModel 类上实现了复制、粘贴以及 CanCopy 和 CanPaste 的方法.如果合适,我可以很容易地实现指向这些的 MVVM-Light RelayCommands,但这似乎不对.
I have a TreeView
that I want to be able to copy and paste nodes in. Each TreeViewItem has its own ViewModel, and they are displayed via HierarchicalDataTemplates
in XAML as there are several different types. I have implemented methods to copy, paste, as well as CanCopy and CanPaste on my ViewModel classes. If appropriate, I could implement MVVM-Light RelayCommands pointing to these easily enough, but that doesn't seem right.
我想使用菜单、Ctrl+C 和 Ctrl+V 或最终使用上下文菜单访问命令.我也不想破坏 UI 中其他元素的复制/粘贴功能,例如文本框.为此目的使用内置的 ApplicationCommands 似乎是合适的.但是,我只看到在 UserControl 代码隐藏中处理这些的示例.我没有(或需要)UserControl,也没有真正遵循 MVVM.
I would like to access the commands using a menu, Ctrl+C and Ctrl+V, or eventually a context menu. I also don't want to break copy/paste functionality for other elements in my UI, such as TextBoxes. It seems appropriate to use the built-in ApplicationCommands for this purpose. However, I am only seeing examples of these being handled in a UserControl code-behind. I don't have (or otherwise need) a UserControl, nor is that really following MVVM.
有什么方法可以将 ApplicationCommand.Copy
和 ApplicationCommand.Paste
命令绑定到我的 ViewModel,即在数据模板中?
Is there a way I can bind ApplicationCommand.Copy
and ApplicationCommand.Paste
commands to my ViewModels, i.e., in the data templates?
推荐答案
我已经使用附加到 TreeView 的行为解决了这个问题.TreeViewItems 或模板似乎没有将命令路由到它们.幸运的是,TreeView 还有一个 SelectedItem 属性,可以用来获取 ViewModel!
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!
(行为在概念上类似于@Natxo 答案中链接中的解决方案,但它并不能解决所有问题.)
(Behaviors are conceptually similar to the solution in the link in @Natxo's answer, but it doesn't resolve everything.)
行为类:
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>
这篇关于如何将 ApplicationCommands 绑定到 ViewModel?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!