【问题标题】:DelegateCommand is not invoked in context menu未在上下文菜单中调用 DelegateCommand
【发布时间】:2014-07-29 08:13:28
【问题描述】:

我似乎无法让这个右键弹出菜单工作。

<TreeView Name="NavigationPanel" ItemsSource="{Binding NavigationList}" />
<Style TargetType="{x:Type TreeViewItem}" >
    <Setter Property="ContextMenu">
        <Setter.Value>
            <ContextMenu  DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TreeView}}, Path=DataContext}">
                <MenuItem Header="Delete" Command="{Binding Path=CommandPopupClick}" CommandParameter="{Binding Path=SelectedItem}"/>
                <Separator />
                <MenuItem Header="Properties" Command="{Binding Path=CommandPopupClick}" CommandParameter="{Binding Path=SelectedItem}"/>
            </ContextMenu>
        </Setter.Value>
    </Setter>
</Style>
//Delegated command
public DelegateCommand CommandPopupClick { get; set; } 

//Assigning the delegate command.
CommandPopupClick = new DelegateCommand(PopupClick, CanMyCommand);

//Event for rightclick option clicked
public void PopupClick(Object Parameters)
{
    var something = Parameters; //Break is here to see if the event fires
}

我可以看到包含“删除”和“属性”项的弹出菜单。但是,当我单击其中任何一个时,它都不会触发事件。

注意:委托命令系统适用于其他一切,我认为这不是问题。

如果可以的话,我真的不想使用Name.Click += new RoutedEvent()

谢谢。

按要求调试错误

A first chance exception of type 'System.IO.FileNotFoundException' occurred in mscorlib.dll
A first chance exception of type 'System.IO.FileNotFoundException' occurred in mscorlib.dll
'Enterprise.exe' (CLR v4.0.30319: Enterprise.exe): Loaded 'Microsoft.GeneratedCode'. 
'Enterprise.exe' (CLR v4.0.30319: Enterprise.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\PresentationFramework-SystemCore\v4.0_4.0.0.0__b77a5c561934e089\PresentationFramework-SystemCore.dll'. Cannot find or open the PDB file.
A first chance exception of type 'System.IO.IOException' occurred in PresentationFramework.dll
A first chance exception of type 'System.IO.IOException' occurred in PresentationCore.dll
'Enterprise.exe' (CLR v4.0.30319: Enterprise.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\UIAutomationTypes\v4.0_4.0.0.0__31bf3856ad364e35\UIAutomationTypes.dll'. Cannot find or open the PDB file.
The thread 0x1954 has exited with code 259 (0x103).

分辨率:

    <Setter Property="ContextMenu">
        <Setter.Value>
            <ContextMenu DataContext="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
                <MenuItem Header="Delete" 
                          Command="{Binding CommandPopupClick}" 
                          CommandParameter="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource  AncestorType=ContextMenu}}" 
                          CommandTarget="{Binding PlacementTarget, RelativeSource={RelativeSource Self}}" />
            </ContextMenu>
        </Setter.Value>
    </Setter>
</Style>

<TreeView Name="NavigationPanel" ItemsSource="{Binding NavigationList}" Tag="{Binding Path=DataContext, ElementName=Main}"/>

感谢所有提供帮助的人。

【问题讨论】:

  • 绑定有数据错误吗?调试时检查输出窗格。
  • 按要求添加错误代码。
  • 很遗憾,它们都不是数据绑定错误,请查看打开上下文菜单或单击菜单时是否出现任何数据错误。
  • 你可以尝试在MenuItem上设置DataContext而不是父ContextMenu吗?
  • 右键单击该项目并打开上下文菜单时没有错误。当我单击菜单项时,输出窗口中没有输出

标签: c# wpf xaml contextmenu


【解决方案1】:

您不能使用RelativeSource BindingContextMenu 访问TreeView.DataContext,因为它在主 UI 视觉树中不是。这是一个非常有据可查的问题,解决方案是使用 ContextMeny.PlacementTarget 属性和应用了Contextmenu 的对象上的Tag 属性将DataContext 对象传递给ContextMenu

我已经写了很多次了,现在我更愿意请求您阅读我对 Stack Overflow 上的 ContextMenu.PlacementTarget is not getting set, no idea whyAdd context menu in datagrid, how to get the select Item value 问题的回答,以获得完整的解释和代码示例。如果您需要进一步的帮助,只需在 Internet 上搜索“WPF ContextMenu DataContext”或类似内容,您应该会找到数十个关于这个确切主题的教程。

【讨论】:

  • 感谢这给了我解决问题所需的详细信息
【解决方案2】:

ContextMenu 不属于可视树,因此FindAncestory 数据绑定将不起作用。

您可以在ContextMenu上明确设置DataContext

例如如果可以的话,您可以直接在 XAML 中创建 ViewModel / DataContext 的实例。

<Style TargetType="{x:Type TreeViewItem}">
  <Setter Property="ContextMenu">
    <Setter.Value>
      <ContextMenu>
        <ContextMenu.DataContext>
          <local:MyViewModel/>
        </ContextMenu.DataContext>

        <MenuItem Command="{Binding Path=CommandPopupClick}"
                  CommandParameter="{Binding Path=SelectedItem}"
                  Header="Delete" />
        <Separator />
        <MenuItem Command="{Binding Path=CommandPopupClick}"
                  CommandParameter="{Binding Path=SelectedItem}"
                  Header="Properties" />
      </ContextMenu>
    </Setter.Value>
  </Setter>
</Style>

或从StaticResource 获取。

  <Window.Resources>
    <local:MyViewModel x:Key="ctx"/>

    <Style TargetType="{x:Type TreeViewItem}">
      <Setter Property="ContextMenu">
        <Setter.Value>
          <ContextMenu DataContext="{StaticResource ctx}">

            <MenuItem Command="{Binding Path=CommandPopupClick}"
                      CommandParameter="{Binding Path=SelectedItem}"
                      Header="Delete" />
            ....

          </ContextMenu>
        </Setter.Value>
      </Setter>
    </Style>
  </Window.Resources>

【讨论】:

  • 是的,这确实有效。但是您说这两个都创建了我的视图模型的新实例?
【解决方案3】:

自从学习越来越多关于 C# 和 WPF 的知识以来,如果其他人正在寻找有关此问题的答案。 答案很简单。

你的做法是错误的。 如果您需要一遍又一遍地使用“行为”并且您使用 MVVM 样式代码(或者您认为您是因为它可能还没有完全实现) 您需要使用他们所谓的附加属性。

简单地说。

  1. 创建附加的属性类。 http://dotnetbyexample.blogspot.com.au/2010/05/attached-dependency-properties-for.html 应该让你开始
  2. 为下面的菜单项示例创建一个模板
  3. 创建标准菜单项。
  4. 在您的附加属性 PropertyMetadata 事件处理程序中处理所有内容。

     <Style TargetType="MenuItem">
          <Setter Property="Properties:ControlMenuItem.InvokeClick" Value="{Binding  RelativeSource={RelativeSource Self}}"/>
     </Style>
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-25
    相关资源
    最近更新 更多