我在我的项目中使用了AvalonEdit控件。当我使用快捷键(如Ctrl+C或Ctrl+V)时,关联的复制/粘贴命令工作正常。我决定在上下文菜单中使用这些命令以获得更多的可用性,因为有些用户习惯于右键单击而不是快捷方式。我使用以下XAML代码进行控制:
<avalonedit:TextEditor.ContextMenu>
<ContextMenu>
<MenuItem Command="Undo" />
<MenuItem Command="Redo" />
<Separator/>
<MenuItem Command="Cut" />
<MenuItem Command="Copy" />
<MenuItem Command="Paste" />
</ContextMenu>
</avalonedit:TextEditor.ContextMenu>
但是当我运行程序时,这些命令总是在上下文菜单中显示为禁用,如下所示:
当我第一次遇到这个问题时,我发布了一个不同的问题,但在MD.Unicorn的帮助下(正如你在下面的评论中看到的那样),我意识到当你把AvalonEdit放在ListBox或ListView命令的ItemTemplate中时,它不起作用。
在MD.unicorn的帮助下,我创建了以下测试代码来重现结果:
ViewModel类和一个简单的数据模板类
public class MyViewModel : INotifyPropertyChanged
{
public MyViewModel()
{
collection = new ObservableCollection<myClass>();
mc = new myClass();
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propName)
{
var h = PropertyChanged;
if (h != null)
h(this, new PropertyChangedEventArgs(propName));
}
public ObservableCollection<myClass> collection { get; set; }
public myClass mc { get; set; }
}
public class myClass
{
public string text { get; set; }
}
public partial class MainWindow : Window
{
MyViewModel _viewModel = new MyViewModel();
public MainWindow()
{
InitializeComponent();
this.DataContext = _viewModel;
}
}
和主窗口的XAML代码
<Window.Resources>
<DataTemplate DataType="{x:Type local:myClass}">
<StackPanel>
<avalonedit:TextEditor x:Name="xmlMessage"
SyntaxHighlighting="XML" ShowLineNumbers="True" >
<avalonedit:TextEditor.ContextMenu>
<ContextMenu>
<MenuItem Command="Undo" />
<MenuItem Command="Redo" />
<Separator/>
<MenuItem Command="Cut" />
<MenuItem Command="Copy" />
<MenuItem Command="Paste" />
</ContextMenu>
</avalonedit:TextEditor.ContextMenu>
</avalonedit:TextEditor>
<TextBox Text="test" />
</StackPanel>
</DataTemplate>
</Window.Resources>
<DockPanel>
<ListView ItemsSource="{Binding collection}" />
<ContentControl Content="{Binding mc}" />
</DockPanel>
如果你尝试这个测试,你可以看到,如果DataTemplate被用在一个内容控件上,它在上下文菜单中的命令绑定工作正常,但是在ListViewItem中它们被禁用了。还要注意的是,DataTemplate中的上下文菜单对于TextBox工作得很好,这表明ListView本身并不会破坏命令链。
我如何修复上下文菜单并挂钩到listView项目中的控制命令?
2条答案
按热度按时间qxgroojn1#
这是我过去用来解决类似问题的方法-我希望它对人们有用(这个一般逻辑可以应用于各种Avalon编辑器相关问题)。
实际发生的可能是阿瓦隆的故障(与
ListItem
等组合)。它搞乱了鼠标处理,我猜重点(这应该是在TextArea
的命令和CanExecute
的工作。mouse handling
是问题所在-就好像你只需按windows context menu
键,它就会弹出一个常规菜单,其中包含启用的命令。Avalon编辑器有一个复杂的鼠标/键处理(很难成为一个好的编辑器)-在键盘上,它在TextArea上显式地执行'focus
'。您还可以通过在实际处理ApplicationCommands.Copy
的CanCutOrCopy
方法(Editing/EditingCommandHandler.cs
,下载Avalon源代码)上设置断点来查看问题。对于“键盘”菜单,它首先进入那里,然后弹出。对于“鼠标",它会弹出-然后在退出时检查CanExecute
(进入该方法)。这都是错的!**还有勘误表...
你自己的命令没有问题,只要正常地暴露你的命令,所有的命令都应该工作。
对于
ApplicationCommands
(即RoutedCommand
)它没有正确布线-Execute
,CanExecute
没有去它应该去的地方,即。TextArea
。为了纠正这个问题,你需要将命令rewire
到你自己的 Package 器中-基本上调用TextArea处理-这只是几行代码,但这是一个必要的步骤(我不认为有一个更“漂亮”的解决方案,除了修复Avalon代码-这可能是一个痛苦,从来没有想过)。(all是基于你的例子-填写我遗漏的空白)你的XAML:
代码隐藏视图模型:
(note:我离开了命名,因为你把它-但请不要使用小型大写的 prop :)
(note:只需将
Window.DataContext
连接到view-model,就像您所做的那样)和两个自定义类来进行 Package 。
备注:
EditText
只是一个依赖属性-能够bind
一个文本(你的text
)-这是阿瓦隆的缺点。只是为了好玩,但你可能需要它,所以我把它留在里面了。使用
AvalonRelayCommand
重新连接应用程序路由的命令-对于其他东西,使用您自己的命令实现。这两个类是核心。您需要使用
AvalonTextEditor
而不是TextEditor -它只是一个很小的 Package 器-将ContextMenu
与TextEditor
挂钩(除了其他问题,菜单项是suffering
,因为缺少visual tree
-并且您无法轻松地从中获得任何控件)。我们需要从CommandParameter
(设置为ContextMenu
)获取TextEditor
的引用。这可以通过一些附件属性来完成(w/o覆盖TextEditor),但这样似乎更干净。在XAML方面--只有一些小的改变--使用 Package 器编辑器--你有一个
MenuItem
样式,injects
是每个命令的正确参数(你可以用其他方式来做,这样更好)。这不是一个
hack
-我们只是通过手动调用TextArea
命令处理来缩短鼠标处理的缺点。差不多就是这样。好好享受吧!
9rnv2umw2#
可能对大多数人来说已经太晚了,但我在菜单项中使用CommandTarget解决了这个问题:
HTH。