2017-08-07 41 views
2

那么,我有一个WPF项目,并且正在使用Visual Studio 2010.我正在使用C#和XAML,并且正在使用MVVM模式。从不起作用的上下文菜单中的命令

我有问题必须是简单的,但我不明白为什么它不工作。

好的,所以我有一个ListBox项目。在那个ListBox中有很多ChatNodes;每个视觉呈现。 ChatNode的视觉元素在这里:

<ControlTemplate x:Key="NodeVisualTemplate"> 
      <Grid> 
       <Border BorderThickness="2" Margin="2" CornerRadius="5,5,5,5" BorderBrush="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}, Path=DataContext.SelectionMode, Converter={StaticResource SelectionModeToColourConverter}}" ContextMenu="{StaticResource ChatNodeMenu}"> 
        <StackPanel Opacity="{Binding IsInvisibleNode, Converter={StaticResource ResourceKey=VisibleToOpacityConverter}}"> 
         <TextBlock Text="Test" Background="AntiqueWhite"/> 
         <TextBlock Text="{Binding Path=NodeText}" Background="Aqua"/> 
         <StackPanel Orientation="Horizontal"> 
          <TextBox Text="Type here" MinWidth="50"/> 
          <Image Source="{StaticResource ImgFolder}" Margin="0,0,5,0" Width="32" Height="32"/> 
         </StackPanel> 
        </StackPanel> 
       </Border> 
      </Grid> 
     </ControlTemplate> 

我将您的注意力吸引到BorderBrush边框。我将在这里再次展示:

BorderBrush="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}, Path=DataContext.SelectionMode, Converter={StaticResource SelectionModeToColourConverter}}" 

此代码位于ListBoxItem中,并且能够找到父列表框,然后访问它的一个属性。这工作正常。该物业是在一个视图模型称为ChatNodeListViewModel,看起来像这样:

private int _selectionMode = 0; 
    public int SelectionMode 
    { 
     get { return _selectionMode; } 
     set 
     { 
      if (_selectionMode != value) 
      { 
       _selectionMode = value; 
       RaisePropertyChanged("SelectionMode"); 
      } 
     } 
    } 

我说出来,特别是因为另一件事是几乎相同的不工作,即使这BorderBrush代码工作。

因此,对不工作的部分。

在上面的那个ControlTemplate中,我们看到一个叫做'ChatNodeMenu'的ContextMenu。这是如下:

<ContextMenu x:Key="ChatNodeMenu" > 
      <MenuItem Header="Remove" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}, Path=DataContext.RemoveChatNodeCommand}" /> 
     </ContextMenu> 

它具有相同的绑定,只有这次它是一个命令称为'RemoveChatNodeCommand'。该菜单确实出现在ChatNode上,右键单击,但该命令不运行。我实际上在我的项目的其他部分使用了几乎相同的代码,所以我认为这是正确的......但显然在某处存在错误。

那么这个命令在哪里?这是被称为“ChatNodeListViewModel”视图模型,我将在此介绍它:

void RemoveChatNodeExecute() 
    { 
     MessageBox.Show("Remove chat node"); 
     return; 
    } 

    bool CanRemoveChatNode() 
    { 
     return true; 
    } 

    public ICommand RemoveChatNodeCommand { get { return new RelayCommand(RemoveChatNodeExecute, CanRemoveChatNode); } } 

我也曾在我的代码中的许多地方使用这个和它的工作每次但是这一个。

所以,无论是代码中的错误还是一个简单的错误。我已经检查过命令的名称并重新复制了好几次。我已经检查过我的代码中使用相同代码的其他部分,但是我看不到任何错误。我已经清理并重建了我的项目以防万一。

如果有人可以冒险猜测,我会很高兴。

+0

如何你应用ContextMenu和哪个元素? – mm8

+0

我通常解决这些问题的方式是将我的绑定输出到标签中(或通过读取绑定错误日志)。你应该尝试做同样的事情。通常用这种方法,你可以检测到涉及使用wpf的大多数问题。 – Dbl

+0

如果您查看发布代码的顶部(控制模板),Border的最终属性是ContextMenu。 – TheFaithfulLearner

回答

2

ListBox不是ContextMenu的视觉祖先,但你可以在BorderTag属性设置为ListBox,然后绑定到ContextMenuPlacementTarget

<Border ... Tag="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}" ContextMenu="{StaticResource ChatNodeMenu}"> 

<MenuItem Header="Remove" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}, Path=PlacementTarget.Tag.DataContext.RemoveChatNodeCommand}" /> 
+0

祝福您先生。 – TheFaithfulLearner