命令和菜单

发布于 2024-12-29 08:04:37 字数 2458 浏览 2 评论 0原文

我已经构建了一个 UserControl,其中包含许多包含 TextBlock 控件的边框。 TextBlocks 的 Text 属性设置为我的 ViewModel 对象中的数据。

我已经向 UserControl 的资源添加了几个上下文菜单:

<UserControl.Resources>
    <ContextMenu x:Key="ContextMenu">
        <MenuItem Header="Copy Plate"   Command="cs:CarSystemCommands.CopyPlateCommand" />
        <MenuItem Header="Search Plate" Command="cs:CarSystemCommands.SearchPlateCommand" />
    </ContextMenu>
    <ContextMenu x:Key="TextBoxContextMenu">
        <MenuItem Header="_Copy"        Command="Copy" />
        <MenuItem Header="Copy Plate"   Command="cs:CarSystemCommands.CopyPlateCommand" />
        <MenuItem Header="Search Plate" Command="cs:CarSystemCommands.SearchPlateCommand" />
    </ContextMenu>
</UserControl.Resources>

我已经向我的 TextBlocks 添加了对上下文菜单的引用。下面是一个示例:

<Border Background="#FFFFFF78" 
        BorderBrush="Black" 
        BorderThickness="2" 
        ContextMenu="{StaticResource TextBoxContextMenu}"
        Grid.Column="0" 
        Margin="5,10,5,5">
    <TextBlock FontSize="18" 
               FontWeight="Bold"
               HorizontalAlignment="Center" 
               Margin="5" 
               x:Name="Camera" 
               VerticalAlignment="Center" />
</Border>

最后,我已将 CommbandBindings 添加到 UserControl:

<UserControl.CommandBindings>
    <CommandBinding Command="Copy"                                  CanExecute="CopyCommand_CanExecute" Executed="CopyCommand_Executed" />
    <CommandBinding Command="cs:CarSystemCommands.CopyPlateCommand" CanExecute="CopyCommand_CanExecute" Executed="CopyPlateCommand_Executed" />
</UserControl.CommandBindings>

迄今为止,我遇到了两个问题:

  1. 当我右键单击控件时,我会看到菜单,但选项呈灰色。我在 CopyCommand_CanExecute、CopyCommand_Executed 和 CopyPlateCommand_Executed 方法的开头放置了断点。到目前为止,这些断点仅在一次运行中被击中。我不知道他们为什么在那次被击中,但之前或之后都没有被击中。如何确保每次都调用 CanExecute 方法?

  2. 有一次断点确实被击中,参数的 Source 属性不是我认为的控件,而是 UserControl。我需要知道 UserControl 上的哪个 TextBlock 引发了事件。我该怎么做?

托尼

编辑:

UserControl 还包含一个 ComboBox 控件。我发现,当我下拉组合框后右键单击 TextBlocks 时,CanExecute 方法确实会运行。我不必在组合框中选择任何内容,只需单击它即可。

你知道 ComboBox 可能在做什么而我的代码没有做什么吗?

另一件事是,下拉 ComboBox 后,执行事件参数的 OriginalSource 就是 ComboBox。我想在几个 TextBlock 上使用相同的复制命令,并且我需要知道使用了哪个 TextBlock 的上下文菜单,以便我知道将哪个 TextBlock 的文本复制到剪贴板。帮助!

I've got a UserControl I've built which contains a number of Borders that contain TextBlock controls. The Text property of the TextBlocks are set to data from my ViewModel object.

I've added a couple of context menus to the UserControl's resources:

<UserControl.Resources>
    <ContextMenu x:Key="ContextMenu">
        <MenuItem Header="Copy Plate"   Command="cs:CarSystemCommands.CopyPlateCommand" />
        <MenuItem Header="Search Plate" Command="cs:CarSystemCommands.SearchPlateCommand" />
    </ContextMenu>
    <ContextMenu x:Key="TextBoxContextMenu">
        <MenuItem Header="_Copy"        Command="Copy" />
        <MenuItem Header="Copy Plate"   Command="cs:CarSystemCommands.CopyPlateCommand" />
        <MenuItem Header="Search Plate" Command="cs:CarSystemCommands.SearchPlateCommand" />
    </ContextMenu>
</UserControl.Resources>

I've added references to the context menus to my TextBlocks. Here's an example:

<Border Background="#FFFFFF78" 
        BorderBrush="Black" 
        BorderThickness="2" 
        ContextMenu="{StaticResource TextBoxContextMenu}"
        Grid.Column="0" 
        Margin="5,10,5,5">
    <TextBlock FontSize="18" 
               FontWeight="Bold"
               HorizontalAlignment="Center" 
               Margin="5" 
               x:Name="Camera" 
               VerticalAlignment="Center" />
</Border>

Finally, I've added CommbandBindings to the UserControl:

<UserControl.CommandBindings>
    <CommandBinding Command="Copy"                                  CanExecute="CopyCommand_CanExecute" Executed="CopyCommand_Executed" />
    <CommandBinding Command="cs:CarSystemCommands.CopyPlateCommand" CanExecute="CopyCommand_CanExecute" Executed="CopyPlateCommand_Executed" />
</UserControl.CommandBindings>

I have two problems with all of this to date:

  1. When I right click on the controls, I see the menus, but the choices are greyed out. I've got breakpoints placed at the start of the CopyCommand_CanExecute, CopyCommand_Executed and CopyPlateCommand_Executed methods. These breakpoints were hit so far in only one run. I don't know why they were hit that time but not before or since. How do I make sure that the CanExecute method is called every time?

  2. The one time the breakpoints did get hit, the argument's Source property wasn't the control I thought it was, it was the UserControl. I need to know which of the TextBlocks on the UserControl raised the event. How do I do that?

Tony

Edit:

The UserControl also contains a ComboBox control. I've found that the CanExecute methods do get run when I right click on the TextBlocks after I drop down the ComboBox. I don't have to select anything in the combobox, I just have to click on it.

Any ideas what the ComboBox might be doing that my code isn't?

The other thing is that after dropping down the ComboBox, the OriginalSource of the Execute event arguments is the ComboBox. I want to use the same Copy command on several of the TextBlocks, and I need to know which one's Context Menu was used so I know which TextBlock's Text to copy to the clipboard. Help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

沉睡月亮 2025-01-05 08:04:37

我找到了我的问题的部分答案。我找到了一种方法,让我的代码可以确定从 ContextMenu 执行了哪个 TextBlock 的复制命令。我没有为需要此命令的三个 TextBlock 使用通用的 ContextMenu,而是为每个 TextBlock 创建了一个单独的 ContextMenu。然后,我将 CommandParameter 添加到该 TextBlock 的“复制”菜单项,其中包含我要复制的属性的名称。然后,在 CopyCommand_Executed 事件处理程序中,我检查 e.Parameter 值并将相应控件的值复制到剪贴板。这很好用。

但是,在我在组合框中选择某些内容之前,CanExecute 事件不会触发的问题仍然存在。我还需要弄清楚这一点。

编辑:

嗯,现在一切似乎都工作正常,包括 CanExecute 事件。我正在尝试各种肯定会破坏某些东西的东西,但现在我已经让 CommandParameter 工作了,其他一切似乎都正常。我将把这个标记为答案。

第二次编辑:

嗯,实际上,当我发布这篇文章时,我正在处理的 UserControl 上的一切都在工作。但是仍然存在问题。

上面提到的 UserControl 实际上嵌入在另一个 UserControl 中第一个 UserControl 的内容包含在 StackPanel 中;我将 StackPanel 设置为 FocusScope,这似乎是

第二个控件的根部有一个 StackPanel,其中有多个 Grid。第一的下面的第二个网格有两个带有 ContextMenus 的 ContextMenus,

我已经将 StackPanel 设为 FocusScope,除非我这样做,否则它们将无法工作 。使它成为 FocusScope,所以它也是一个。最后,我将容纳两个 DataGrid 的网格设为 FocusScope,

我认为问题与 FocusScope 有关,但我不知道如何实现。它是相关的,我尝试过的组合都不起作用。有什么想法吗?

I've found a partial answer to my problem. I figured out a way that my code can determine which TextBlock's Copy command was executed from the ContextMenu. Instead of using a common ContextMenu for the three TextBlocks that need this command, I created a separate ContextMenu for each TextBlock. I then added a CommandParameter to the Copy menu item for that TextBlock with the name of the property I wanted to copy. Then, in the CopyCommand_Executed event handler, I check the value of the e.Parameter value and copy the value of the appropriate control to the clipboard. This works great.

However, my problem with the CanExecute events not firing until I select something in the ComboBox remains. I still need to figure this one out.

Edit:

Well, everything seems to be working fine now, including the CanExecute events. I was trying various things that must have been breaking something, but now that I've got the CommandParameter working, everything else seems OK. I"m going to mark this as the answer.

Second Edit:

Well, actually, everything is working on the UserControl that I was working on when I posted this. But there are still problems.

The UserControl mentioned above is actually embedded in another UserControl. The first UserControl's content is contained in a StackPanel; I set the StackPanel as a FocusScope and that seems to be when everything started working.

The second control has a StackPanel at the root and a number of Grids inside that. The first Grid holds the first UserControl and some other things. A second Grid below that has two DataGrids that have ContextMenus. Its these ContextMenus that aren't working now.

I've made the StackPanel a FocusScope. The context menus on the first UserControl don't work unless I make it a FocusScope, so it is one, too. Finally, I've made the Grid that holds the two DataGrids a FocusScope.

I think the problem has to do with FocusScopes, but I have no idea how it relates, and no combination that I've tried works. Any ideas?

染墨丶若流云 2025-01-05 08:04:37

这个问题已经在我的代码中解决了。事实证明,问题在于 XAML 处理器无法确定命令的目标是什么。也就是说,它无法弄清楚将命令发送到哪里。

我能够使用后面的代码中的代码修复此问题。我仍然对问题的 XAML 修复感兴趣,但我还没有时间研究它。与此同时,我实施的解决方案运行良好。

对于那些感兴趣的人,这里是我编写的设置命令目标的代码:

private void FixMenuItems( FrameworkElement element, Func<MenuItem, bool> condition ) {
    foreach ( MenuItem menuItem in element.ContextMenu.Items ) {
        if ( condition( menuItem ) ) {
            menuItem.CommandTarget = this;
        }
    }
}

要使用该函数,您可以通过要修复该方法的上下文菜单传递对控件的引用,以及一个采用如果 MenuItem 的 CommandTarget 属性应设置为当前对象,则作为参数的 MenuItem 返回 true。

This problem has been resolved in my code. It turns out that the problem was that the XAML processor was not able to determine what the target of the commands were. That is, it couldn't figure out where to send the command to.

I was able to fix this using code in my code behind. I'm still interested in a XAML fix for the problem, but I haven't had time to look into it. In the meantime the solution I've implemented works fine.

For those interested, here is the code I wrote which sets the target of the command:

private void FixMenuItems( FrameworkElement element, Func<MenuItem, bool> condition ) {
    foreach ( MenuItem menuItem in element.ContextMenu.Items ) {
        if ( condition( menuItem ) ) {
            menuItem.CommandTarget = this;
        }
    }
}

To use the function, you pass a reference to the control with the context menu you're trying to fix to the method, along with a function that takes a MenuItem as a parameter returns true if the MenuItem's CommandTarget property should be set to the current object.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文