为什么我的WPF ContextMenu项目被禁用?

时间:2014-08-15 14:32:43

标签: wpf mvvm user-controls command contextmenu

在WPF应用程序中,我的ContextMenu有一个小但烦人的问题 我使用DataTemplate作为我的ViewModel对象列表来创建可视元素。在DataTemplate中,我只需将UserControl设置为:

<!-- Define a data-template for the 'RoomViewModel' class. This generates the UI for each node. -->
<DataTemplate DataType="{x:Type model:RoomViewModel}">
    <network:RoomView network:ConstraintView.ArgumentChanged="ConstraintView_ArgumentChanged"></network:RoomView>
</DataTemplate>

我希望RoomView有一个ContextMenu,如果用户点击MenuItem,应该执行RelayCommand。我对RoomView的UserControl现在看起来像这样:

<UserControl x:Name="userControl" x:Class="NetworkUI.RoomView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:network="clr-namespace:NetworkUI"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300" DataContextChanged="userControl_DataContextChanged">
    <UserControl.Resources>
        <!-- UI commands -->
        <RoutedCommand x:Key="Commands.NewConstraintCmd"></RoutedCommand>
    </UserControl.Resources>
    <UserControl.CommandBindings>
        <CommandBinding x:Name="newConst" Command="{StaticResource Commands.NewConstraintCmd}" Executed="NewConstraint_Executed"></CommandBinding>
    </UserControl.CommandBindings>
    <Grid Width="Auto" Height="Auto" MinWidth="50" >
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>
        <Grid Grid.Row="0" Width="Auto" Height="20" MinWidth="50" >
            <Rectangle Stroke="Black" Fill="White" RadiusX="4" RadiusY="4" SnapsToDevicePixels="True" ></Rectangle>
            <Grid Margin="-4" >
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="*" MinWidth="10" />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="*" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
                <network:EditableTextBlock Grid.Column="1" Grid.Row="1" x:Name="nameTextBox" Text="{Binding Name, Mode=TwoWay}" HorizontalAlignment="Center" VerticalAlignment="Center" BorderBrush="{x:Null}" />
                <network:ConnectorItem Grid.Row="1" Grid.Column="0" DataContext="{Binding Connectors[0]}" />
                <network:ConnectorItem Grid.Row="1" Grid.Column="2" DataContext="{Binding Connectors[1]}" />
            </Grid>
        </Grid>
        <StackPanel Grid.Row="1" x:Name="roomProperties" Width="Auto" HorizontalAlignment="Stretch" >
            <ItemsControl ItemsSource="{Binding PropertyGroups}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <network:ConstraintCollectionView></network:ConstraintCollectionView>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </StackPanel>
    </Grid>
    <UserControl.ContextMenu>
        <ContextMenu x:Name="contextMenu">
            <MenuItem Header="new Constraint" Command="{StaticResource Commands.NewConstraintCmd}"></MenuItem>
        </ContextMenu>
    </UserControl.ContextMenu>
</UserControl>

我不确定我的UserControl代码是否正常。在我的CodeBehind文件中,我定义了一个

public ICommand NewConstraintCmd;

- 当用户单击Item时应执行的命令。我的Executed处理程序很简单,如下所示:

private void NewConstraint_Executed(object sender, ExecutedRoutedEventArgs e) {
    ViewModel.AddConstraint();
}

ViewModel确实是一个RoomViewModel,而NewConstraintCmd是在DataContextChanged - 事件中设置的(此处不显示)。

我的简单问题是,为什么我的ContextMenu-Item始终被禁用?我的意思是从不检查RelayCommand.CanExecute,这可能是问题吗?

我还没有找到解决问题的方法。
谢谢你的帮助!

1 个答案:

答案 0 :(得分:-1)

谢谢Rohit Vats!我将ICommand定义更改为:

public static readonly ICommand NewConstraint = new RelayCommand((rvm) => AddConstraint(rvm));

由于这是一个静态方法,我需要参数(我的RoomView的DataContext) 我的方法现在定义如下:

private static void AddConstraint(object rvm) {
    if (rvm is RoomViewModel)
        (rvm as RoomViewModel).AddConstraint();
}

首先检查参数,如果确定(RoomViewModel对象),我调用对象的实际函数。

我不知道为什么它现在有效,真的:/。

我对MenuItem的XAML代码现在看起来像这样:

<MenuItem Header="new Constraint" Command="network:RoomView.NewConstraint" CommandParameter="{Binding}"></MenuItem>

如前所述,我需要CommandParameter来调用它上面的函数。由于所需的Object是我的DataContext,我只需使用{Binding}来传递对象。

现在这真的很好用,我希望将来也可以使用InputBindings :)! 再次感谢您的帮助!