【问题标题】:Menu Key Bindings are not working菜单键绑定不起作用
【发布时间】:2016-07-15 09:08:40
【问题描述】:

我的菜单快捷方式都不起作用。

我已经阅读了一些关于这个问题的内容,根据答案here 这意味着我需要使用命令而不是点击。

这里是菜单结构:

<MenuItem x:Uid="MenuItem_10" Header="Zoom In" InputGestureText="CTRL +" Click="menuViewZoomInOutScaleFactor" Tag="25">
    <MenuItem.InputBindings>
        <KeyBinding x:Uid="KeyBinding_7" Key="OemPlus" Modifiers="Ctrl" />
    </MenuItem.InputBindings>
</MenuItem>
<MenuItem x:Uid="MenuItem_11" Header="Zoom Out" InputGestureText="CTRL -" Click="menuViewZoomInOutScaleFactor" Tag="-25">
    <MenuItem.InputBindings>
        <KeyBinding x:Uid="KeyBinding_8" Key="OemMinus" Modifiers="Ctrl"/>
    </MenuItem.InputBindings>
</MenuItem>
<Separator x:Uid="Separator_7"/>
<MenuItem x:Uid="MenuItem_12" Header="400%" IsCheckable="True" IsChecked="{Binding Source={x:Static Properties:Settings.Default}, Path=ZoomFactor, Converter={ValueConverters:IsIntegerEqual To=400}, Mode=OneWay}" Tag="400" Click="menuViewZoomScaleFactor"/>
<MenuItem x:Uid="MenuItem_13" Header="300%" IsCheckable="True" IsChecked="{Binding Source={x:Static Properties:Settings.Default}, Path=ZoomFactor, Converter={ValueConverters:IsIntegerEqual To=300}, Mode=OneWay}" Tag="300" Click="menuViewZoomScaleFactor"/>
<MenuItem x:Uid="MenuItem_14" Header="250%" IsCheckable="True" IsChecked="{Binding Source={x:Static Properties:Settings.Default}, Path=ZoomFactor, Converter={ValueConverters:IsIntegerEqual To=250}, Mode=OneWay}" Tag="250" Click="menuViewZoomScaleFactor"/>
<MenuItem x:Uid="MenuItem_15" Header="200%" IsCheckable="True" IsChecked="{Binding Source={x:Static Properties:Settings.Default}, Path=ZoomFactor, Converter={ValueConverters:IsIntegerEqual To=200}, Mode=OneWay}" Tag="200" Click="menuViewZoomScaleFactor"/>
<MenuItem x:Uid="MenuItem_16" Header="175%" IsCheckable="True" IsChecked="{Binding Source={x:Static Properties:Settings.Default}, Path=ZoomFactor, Converter={ValueConverters:IsIntegerEqual To=175}, Mode=OneWay}" Tag="175" Click="menuViewZoomScaleFactor"/>
<MenuItem x:Uid="MenuItem_17" Header="150%" IsCheckable="True" IsChecked="{Binding Source={x:Static Properties:Settings.Default}, Path=ZoomFactor, Converter={ValueConverters:IsIntegerEqual To=150}, Mode=OneWay}" Tag="150" Click="menuViewZoomScaleFactor"/>
<MenuItem x:Uid="MenuItem_18" Header="125%" IsCheckable="True" IsChecked="{Binding Source={x:Static Properties:Settings.Default}, Path=ZoomFactor, Converter={ValueConverters:IsIntegerEqual To=125}, Mode=OneWay}" Tag="125" Click="menuViewZoomScaleFactor"/>
<MenuItem x:Uid="MenuItem_19" Header="100%" IsCheckable="True" InputGestureText="CTRL + 0"  IsChecked="{Binding Source={x:Static Properties:Settings.Default}, Path=ZoomFactor, Converter={ValueConverters:IsIntegerEqual To=100}, Mode=OneWay}" Tag="100" Click="menuViewZoomScaleFactor">
    <MenuItem.InputBindings>
        <KeyBinding x:Uid="KeyBinding_9" Key="D0"  Modifiers="Ctrl"/>
    </MenuItem.InputBindings>
</MenuItem>
<MenuItem x:Uid="MenuItem_20" Header="75%" IsCheckable="True" IsChecked="{Binding Source={x:Static Properties:Settings.Default}, Path=ZoomFactor, Converter={ValueConverters:IsIntegerEqual To=75}, Mode=OneWay}" Tag="75" Click="menuViewZoomScaleFactor"/>
<MenuItem x:Uid="MenuItem_21" Header="50%" IsCheckable="True" IsChecked="{Binding Source={x:Static Properties:Settings.Default}, Path=ZoomFactor, Converter={ValueConverters:IsIntegerEqual To=50}, Mode=OneWay}" Tag="50" Click="menuViewZoomScaleFactor"/>
<Separator x:Uid="Separator_8"/>
<MenuItem x:Uid="MenuItem_22" Header="Custom..."/>

如您所见,其中三个菜单项应与:

  1. Ctrl + 0
  2. Ctrl +
  3. Ctrl -

我在 Keys 列表中找不到这些特定字母,因此选择了 D0OemPlusOemMinus。不管怎样,我的键绑定都没有真正得到处理。为什么?

我看不到如何从使用点击转换为命令。到目前为止,我的所有命令都与视图模型相关联。但在这种情况下,我需要将命令与后面的代码相关联。

这是我当前的点击处理程序:

private void menuViewZoomScaleFactor(object sender, RoutedEventArgs e)
{
    SetZoomFactor(Int32.Parse((String)((MenuItem)sender).Tag));
}

private void menuViewZoomInOutScaleFactor(object sender, RoutedEventArgs e)
{
    int iStep = Int32.Parse((String)((MenuItem)sender).Tag);

    if ((iStep == 25 && Settings.Default.ZoomFactor <= 375) ||
        (iStep == -25 && Settings.Default.ZoomFactor >= 75))
    {
        SetZoomFactor(Settings.Default.ZoomFactor + iStep);
    }
}

private void SetZoomFactor(int iZoomFactor)
{
    Settings.Default.ZoomFactor = iZoomFactor;

    IServiceProvider serviceProvider = myWorkbookView.Document as IServiceProvider;

    Guid SID_SWebBrowserApp = new Guid("0002DF05-0000-0000-C000-000000000046");
    Guid serviceGuid = SID_SWebBrowserApp;

    Guid iid = typeof(SHDocVw.IWebBrowser2).GUID;

    SHDocVw.IWebBrowser2 WebBrowser = (SHDocVw.IWebBrowser2)serviceProvider.QueryService(ref serviceGuid, ref iid);
    WebBrowser.ExecWB(SHDocVw.OLECMDID.OLECMDID_OPTICAL_ZOOM, SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER, Settings.Default.ZoomFactor);
}

所以我必须让我的菜单键绑定起作用。

【问题讨论】:

  • 您没有正确使用InputBindings。看看上面的答案。
  • @EliArbel 我刚刚看过了。我不明白类后面的 MainWindow 代码之外的静态类是如何访问主窗口内容的。
  • 输入绑定不绑定到菜单项 - 它们绑定到命令,也许这就是您的困惑所在。您应该在顶级元素(例如窗口)上设置输入绑定并将它们连接到正确的命令 - 或者 - 使用路由命令可以具有默认手势(许多内置命令都这样做)。
  • @EliArbel 我真的很困惑。我看不到如何使用命令定义后面的代码。

标签: c# wpf menu key-bindings


【解决方案1】:

如果你想在 WPF 中使用InputBindings,你必须使用命令。您需要将命令分配给菜单项以及添加命令绑定和输入手势。您可以使用CommandParameters 将参数传递给命令绑定处理程序。

将路由命令对象视为一个,它定义了命令源(菜单项或输入绑定)和命令绑定之间的链接。命令绑定定义了命令可以运行的可视化树的范围

<Window x:Class="WpfApplication.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:system="clr-namespace:System;assembly=mscorlib"
        Title="MainWindow">
    <Window.CommandBindings>
        <CommandBinding Command="IncreaseZoom"
                        Executed="IncreaseZoom_OnExecuted" />
        <CommandBinding Command="Zoom"
                        Executed="Zoom_OnExecuted" />
    </Window.CommandBindings>
    <Window.InputBindings>
        <KeyBinding Gesture="Ctrl+Plus"
                    Command="IncreaseZoom" />
    </Window.InputBindings>
    <Grid>
        <Menu>
            <MenuItem Header="View">
                <MenuItem x:Uid="MenuItem_10"
                          Header="Zoom In"
                          InputGestureText="CTRL +"
                          Command="IncreaseZoom" />
                <MenuItem x:Uid="MenuItem_12"
                          Header="400%"
                          IsCheckable="True"
                          IsChecked="{Binding Whatever}"
                          Command="Zoom">
                    <MenuItem.CommandParameter>
                        <system:Int32>400</system:Int32>
                    </MenuItem.CommandParameter>
                </MenuItem>
            </MenuItem>
        </Menu>
    </Grid>
</Window>

后面的代码:

private void IncreaseZoom_OnExecuted(object sender, ExecutedRoutedEventArgs e)
{
    IncrementZoom(25);
}

private void Zoom_OnExecuted(object sender, ExecutedRoutedEventArgs e)
{
    var zoom = (int)e.Parameter;
    SetZoom(zoom);
}

如果在内置命令中没有找到合适的命令,可以在静态类中定义自己的:

public static class MyCommands
{
    public static readonly RoutedCommand SampleCommand = new RoutedCommand(
        nameof(SampleCommand), typeof(MyCommands), 
        new InputGestureCollection { new KeyGesture(Key.B, ModifierKeys.Alt) });
}

如您所见,您甚至可以定义默认输入手势,因此您无需在 XAML 中指定额外的输入绑定(仅是命令绑定)。在 XAML 中使用此类:

<MenuItem Command="{x:Static m:MyCommands.SampleCommand}" />

【讨论】:

  • 好的,我取得了进展,我可以让它触发命令。但是除非我单击菜单项,否则该参数为空。如果我只使用 kkeypress 参数为空。如果我点击菜单项,则参数有效。
  • 您也可以在KeyBinding 中传递参数。但你可能不应该那样做。只需使用单独的命令。
  • 好的,这行得通。到达那里。但是......如果我可能会问,难道不能只使用“标签”值作为命令和键绑定的参数吗?这样我只有一个命令。否则我必须定义两个命令。如果需要,我会的。
  • 不,标签是控件的属性。该命令抽象出它是如何激活的。也许你误解了一些东西 - 键绑定和菜单都是命令的独立源,它们没有以任何方式连接。
  • 一个问题:内置命令列表定义在哪里?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多