c# - 上下文菜单中的命令不起作用

标签 c# wpf xaml mvvm

嗯,我有一个 WPF 项目,并且正在使用 Visual Studio 2010。我正在使用 C# 和 XAML,并且正在使用 MVVM 模式。

我遇到的问题一定很简单,但我就是不明白为什么它不起作用。

好吧,我有一个带有列表框的项目。在该列表框中有许多聊天节点;每个都以视觉方式呈现。 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 内部,能够找到父 ListBox,然后访问它的属性。这很好用。该属性位于名为 ChatNodeListViewModel 的 View 模型中,如下所示:

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>

它具有相同的绑定(bind),只是这次它用于名为“RemoveChatNodeCommand”的命令。右键单击 ChatNode 时会出现该菜单,但该命令不会运行。实际上,我在项目的其他部分使用了几乎相同的代码,因此我认为它是正确的......但显然某处存在错误。

那么这个命令在哪里呢?它位于名为“ChatNodeListViewModel”的 View 模型中,我将在这里展示它:

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

    bool CanRemoveChatNode()
    {
        return true;
    }

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

我还在我的代码中的许多地方使用了它,并且每次都有效,但这次除外。

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

如果有人可以大胆猜测,我会非常高兴。

最佳答案

ListBox 不是 ContextMenu 的视觉祖先,但您可以设置 BorderTag 属性> 到 ListBox,然后绑定(bind)到 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}" />

关于c# - 上下文菜单中的命令不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45549898/

相关文章:

c# - Windows 8.1 应用程序是否可以在 Windows 8 PC 上运行?

c# - 使用c#更新MySql上auto_increment ID列的值

c# - 如何以跨平台方式使用 .NET 5 获取硬件信息?

c# - 有没有办法在 ErrorTemplate 中设置工具提示?

c# - 在 WPF 中覆盖 OnStartup

c# - 如何处理 LINQ 语句中的多个 where 子句?

c# - 有没有一种方法可以在不需要管理员权限的情况下与微过滤器进行通信?

c# - 具有 volatile 或内存屏障的双锁

c# - 引用 ControlTemplate 中的控件

wpf - 如何更改 WPF `<Separator/>` 的颜色?