我有这个上下文菜单资源:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ContextMenu x:Key="FooContextMenu">
<ContextMenu.CommandBindings>
<CommandBinding Command="Help" Executed="{Binding ElementName=MainTabs, Path=HelpExecuted}" />
</ContextMenu.CommandBindings>
<MenuItem Command="Help">
<MenuItem.Icon>
<Image Source="../Resources/Icons/Help.png" Stretch="None" />
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</ResourceDictionary>
Run Code Online (Sandbox Code Playgroud)
我想在两个地方重复使用它.首先,我试图把它放在DataGrid:
<DataGrid ContextMenu="{DynamicResource FooContextMenu}">...
Run Code Online (Sandbox Code Playgroud)
它ContextMenu本身工作正常,但Executed="..."我现在打破了应用程序并抛出:
PresentationFramework.dll中出现"System.InvalidCastException"类型的第一次机会异常
附加信息:无法将类型为"System.Reflection.RuntimeEventInfo"的对象强制转换为"System.Reflection.MethodInfo".
如果我删除整个Executed="..."定义,那么代码就可以工作(并且命令不会执行任何操作/灰显).一旦我右键单击网格/打开上下文菜单,就会抛出异常.
它DataGrid被放置在几个元素之下,但最终它们都在一个TabControl(被调用的MainTabs)下面,它被ItemsSource设置为一个FooViewModels 的集合,并且FooViewModel我有一个HelpExecuted我想要被调用的方法.
让我们想象一下:
ItemsSource=ObservableCollection<FooViewModel>,x:Name=MainTabs)
为什么会出现这个错误,我怎样才能使上下文菜单命令"目标"的FooViewModel的HelpExecuted方法是什么?
不幸的是,您无法绑定Executeda ContextMenu,因为它是一个事件。另一个问题是,在您的应用程序的其余ContextMenu部分中不存在该问题VisualTree。这两个问题都有解决方案。
首先,您可以使用Tag父控件的属性来ContextMenu传递DataContext应用程序的。然后你就可以使用DelegateCommand你的了CommandBinding,然后就可以了。这是一个小示例View,显示了ViewModel以及DelegateCommand您必须添加到项目中的实现。
DelegateCommand.cs
public class DelegateCommand : ICommand
{
private readonly Action<object> execute;
private readonly Predicate<object> canExecute;
public DelegateCommand(Action<object> execute)
: this(execute, null)
{ }
public DelegateCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
this.execute = execute;
this.canExecute = canExecute;
}
#region ICommand Members
[DebuggerStepThrough]
public bool CanExecute(object parameter)
{
return canExecute == null ? true : canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
execute(parameter);
}
#endregion
}
Run Code Online (Sandbox Code Playgroud)
主窗口视图.xaml
<Window x:Class="Application.MainWindowView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindowView" Height="300" Width="300"
x:Name="MainWindow">
<Window.Resources>
<ResourceDictionary>
<ContextMenu x:Key="FooContextMenu">
<MenuItem Header="Help" Command="{Binding PlacementTarget.Tag.HelpExecuted, RelativeSource={RelativeSource AncestorType=ContextMenu}}" />
</ContextMenu>
</ResourceDictionary>
</Window.Resources>
<Grid>
<TabControl ItemsSource="{Binding FooViewModels}" x:Name="MainTabs">
<TabControl.ContentTemplate>
<DataTemplate>
<DataGrid ContextMenu="{DynamicResource FooContextMenu}" Tag="{Binding}" />
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
</Grid>
</Window>
Run Code Online (Sandbox Code Playgroud)
MainWindowView.xaml.cs
public partial class MainWindowView : Window
{
public MainWindowView()
{
InitializeComponent();
DataContext = new MainWindowViewModel();
}
}
Run Code Online (Sandbox Code Playgroud)
MainWindowViewModel.cs
public class MainWindowViewModel
{
public ObservableCollection<FooViewModel> FooViewModels { get; set; }
public MainWindowViewModel()
{
FooViewModels = new ObservableCollection<FooViewModel>();
}
}
Run Code Online (Sandbox Code Playgroud)
FooViewModel.cs
public class FooViewModel
{
public ICommand HelpExecuted { get; set; }
public FooViewModel()
{
HelpExecuted = new DelegateCommand(ShowHelp);
}
private void ShowHelp(object obj)
{
// Yay!
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4502 次 |
| 最近记录: |