【问题标题】:Menu not closing after clicking a MenuItem with a bound command in WPF在 WPF 中单击带有绑定命令的 MenuItem 后菜单未关闭
【发布时间】:2017-04-09 08:09:30
【问题描述】:

我有一个自定义的 Menu 和 MenuItems,每个 MenuItem 都绑定了一个特定的命令。我的问题是,当我单击任何 MenuItem 时,命令会执行但菜单没有关闭。

这是一个带有一个 MenuItem 的菜单示例

<Menu Background="#f4f4f4" x:Name="ExportMenu">
<Menu.ItemsPanel>
    <ItemsPanelTemplate>
        <StackPanel Orientation="Vertical" Background="#f4f4f4"/>
    </ItemsPanelTemplate>
</Menu.ItemsPanel>
    <MenuItem x:Name="CopyItem" Header="Copy" Style="{DynamicResource MainMenuItem}"
                CommandParameter="{Binding Data.CurrentPlotVMs, Source={StaticResource Proxy}}"
                Command="{Binding Data.ExporterVM.CopyGraphicPlotsCommand, Source={StaticResource Proxy}}" Click="CopyItem_Click">
    <MenuItem.Icon>
        <TextBlock Text="" FontSize="15" FontFamily="../Icons/#icons"/>
    </MenuItem.Icon>
</MenuItem>
</Menu>

这是我的自定义样式

<Style x:Key="MainMenuItem" TargetType="{x:Type MenuItem}">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="FontFamily" Value="Open Sans"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="FontWeight" Value="Light"/>
<Setter Property="StaysOpenOnClick" Value="False"/>
<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="{x:Type MenuItem}">
            <Border x:Name="templateRoot" BorderThickness="0" Background="#f4f4f4" SnapsToDevicePixels="True" Padding="0,10,10,10">
                <Grid VerticalAlignment="Center">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="Auto"/>
                    </Grid.ColumnDefinitions>
                    <ContentPresenter x:Name="Icon" 
                                      Grid.Column="0"
                                      Content="{TemplateBinding Icon}" 
                                      ContentSource="Icon" 
                                      HorizontalAlignment="Center" Height="16" Width="16"
                                      Margin="5,0,5,0"
                                      SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 
                                      VerticalAlignment="Center"/>
                    <ContentPresenter ContentTemplate="{TemplateBinding HeaderTemplate}" 
                                      Content="{TemplateBinding Header}" 
                                      Grid.Column="1" 
                                      ContentStringFormat="{TemplateBinding HeaderStringFormat}" 
                                      ContentSource="Header" 
                                      Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                </Grid>
            </Border>
            <ControlTemplate.Triggers>
                <Trigger Property="IsMouseOver" Value="true">
                    <Setter TargetName="templateRoot" Property="Background" Value="{StaticResource ResourceKey=FrSkyBlue}"/>
                    <Setter Property="Foreground" Value="{StaticResource FrWhite}"/>
                    <Setter Property="Cursor" Value="Hand"/>
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </Setter.Value>
</Setter>
</Style>

也许我设置了错误的属性或做错了其他事情,我对 WPF 和 MVVM 有点陌生。

【问题讨论】:

  • CopyItem_Click 是做什么的?为什么需要命令点击处理程序?
  • 它只是改变一个图标的可见性,菜单有一个图标,根据点击的项目而变化。每个项目都有一个命令绑定,可以为我的项目执行所需的操作,点击事件只是处理视图中图标的可见性。

标签: c# wpf xaml mvvm


【解决方案1】:

您不能将Click eventCommand 用于同一个按钮/控件:

我假设在 CopyItem_Click() 方法中,您正在关闭菜单 - 您必须决定是使用 MVVM 模型还是没有此模式的简单 XAML 应用程序。

如果这是更简单的版本,您可以在 Click 方法中处理:

private void CopyItem_Click(object sender, ...)
{
    var cmd = CopyItem.Command;
    var param = CopyItem.CommandParameter;

    if(cmd != null && cmd.CanExecute(param))
        cmd.Execute(param);

    // add the code for closing menu
}

该案例的另一种方法是使用 MVVM 模型。您应该完全避免使用Click 事件处理,而是将其推送到命令中。命令本身会完成这项工作,之后必须关闭菜单。

public RelayCommand MyCommand 
{ 
    get; 
    private set; 
}

public MainViewModel() 
{ 
    MyCommand = new RelayCommand(ExecuteMyCommand); 
} 

private void ExecuteMyCommand() 
{ 
    // Do the work You expect

    // Close the menu
}

一些源代码:

【讨论】:

  • 感谢您的澄清,我没有关闭 CopyItem_Click 中的菜单,我只是更改了视图中图标的可见性。但我现在明白了,如果我使用 MVVM,我不能同时拥有一个命令和一个 Click 事件,我将不得不管理另一种方式来处理图标的可见性。
猜你喜欢
  • 1970-01-01
  • 2020-10-30
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
  • 2019-01-04
  • 2016-02-29
  • 1970-01-01
相关资源
最近更新 更多