来自上下文菜单的命令不起作用

时间:2017-08-07 14:54:04

标签: c# wpf xaml mvvm

好吧,我有一个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 for the Border。我将在这里再次展示:

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

此代码位于ListBoxItem内,并且能够找到父ListBox,然后访问它的属性。这很好用。该属性位于名为ChatNodeListViewModel的视图模型中,如下所示:

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

我特别提到它是因为另一个几乎相同的东西不起作用,即使这个BorderBrush代码正常工作。

所以,对于不工作的部分。

在上面的相同ControlTemplate中,我们看到一个名为&#39; ChatNodeMenu&#39;的ContextMenu。具体如下:

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

它具有相同的绑定,但这次仅适用于名为&#39; RemoveChatNodeCommand&#39;的命令。右键单击ChatNode时菜单会出现,但该命令不会运行。我实际上在项目的其他部分使用了几乎相同的代码,所以我认为它是正确的...但显然在某处有错误。

那么这个命令在哪里?它位于名为&#39; ChatNodeListViewModel&#39;的视图模型中。我会在这里介绍一下:

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

    bool CanRemoveChatNode()
    {
        return true;
    }

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

我也在我的代码中的许多地方使用过它,并且它每次都有效但是这个。

所以,要么是代码中的错误,要么是一个简单的错误。我检查了命令的名称并重新复制了几次。我已经检查了我的代码的其他部分,我使用了相同的代码,但我看不出有什么问题。为了以防万一,我已经清理并重建了我的项目。

如果有人冒险猜测,我会对此非常满意。

1 个答案:

答案 0 :(得分:2)

ListBox不是ContextMenu的视觉祖先,但您可以将Tag的{​​{1}}属性设置为Border,然后绑定到ListBox PlacementTarget的{​​{1}}:

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