gpt4 book ai didi

c# - 如何在 WPF 中实现使用祖先方法的命令?

转载 作者:太空狗 更新时间:2023-10-29 20:05:39 25 4
gpt4 key购买 nike

我有这个上下文菜单资源:

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

我想在两个地方重新使用它。首先我试图把它放在 DataGrid 中。 :

<DataGrid ContextMenu="{DynamicResource FooContextMenu}">...

ContextMenu本身工作正常,但与 Executed="..."我现在破坏了应用程序并抛出:

A first chance exception of type 'System.InvalidCastException' occurred in PresentationFramework.dll

Additional information: Unable to cast object of type 'System.Reflection.RuntimeEventInfo' to type 'System.Reflection.MethodInfo'.

如果我删除整个 Executed="..."定义,然后代码工作(并且命令不执行任何操作/变灰)。只要我右键单击网格/打开上下文菜单,就会抛出异常。

DataGrid被放置在一些元素下面,但最终它们都在 TabControl 下面(称为 MainTabs )具有 ItemsSource设置为 FooViewModel 的集合s,在那FooViewModel我有一个方法 HelpExecuted我想被称为。

让我们想象一下:

  • 选项卡控件 ( ItemsSource=ObservableCollection<FooViewModel> , x:Name=MainTabs )
    • 网格
      • 更多用户界面
        • DataGrid(设置了上下文菜单)

为什么会出现此错误以及如何使上下文菜单命令“定位”FooViewModelHelpExecuted方法?

最佳答案

不幸的是,您不能为 ContextMenu 绑定(bind) Executed,因为它是一个事件。另一个问题是 ContextMenuVisualTree 中不存在,您的应用程序的其余部分存在。这两个问题都有解决方案。

首先,您可以使用ContextMenu 父控件的Tag 属性来传递应用程序的DataContext。然后你可以为你的 CommandBinding 使用 DelegateCommand 就可以了。这是一个小示例,显示了您必须添加到项目中的 ViewViewModelDelegateCommand 实现。

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
}

MainWindowView.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>

MainWindowView.xaml.cs

public partial class MainWindowView : Window
{
public MainWindowView()
{
InitializeComponent();
DataContext = new MainWindowViewModel();
}
}

MainWindowViewModel.cs

public class MainWindowViewModel
{
public ObservableCollection<FooViewModel> FooViewModels { get; set; }

public MainWindowViewModel()
{
FooViewModels = new ObservableCollection<FooViewModel>();
}
}

FooViewModel.cs

public class FooViewModel
{
public ICommand HelpExecuted { get; set; }

public FooViewModel()
{
HelpExecuted = new DelegateCommand(ShowHelp);
}

private void ShowHelp(object obj)
{
// Yay!
}
}

关于c# - 如何在 WPF 中实现使用祖先方法的命令?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10365582/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com