【问题标题】:VSIX window - key shortcut to execute ICommandVSIX 窗口 - 执行 ICommand 的快捷键
【发布时间】:2017-03-13 13:01:37
【问题描述】:

拥有一个 Visual Studio 扩展 (VSIX) 项目:在Window 中,我们得到了UserControl,其中Button 绑定到一些ICommand。这可以按预期完美运行,但是我想附加一个快捷键(例如:CTRL + S),它会触发相同的Command

我检查了几个问题,其中我发现这段代码最有用:

<UserControl.InputBindings>
    <KeyBinding Modifiers="Ctrl" Key="Esc" Command="{Binding SaveCmd}"/>
</UserControl.InputBindings>

但是Command 从未被按键触发,我认为问题可能是:

  • 上面的代码不应该工作? (我发现应该使用DependencyProperty 绑定到Command 的文章)
  • 按键被 Visual Studio 本身捕获(CTRL + S 正在保存文件)
  • 我可能需要在封装UserControlWindow 上设置绑定
  • 我可能需要在 *Package.vsct 中设置绑定并将其路由到 Visual Studio 中的 Command

问题:我想如何绑定到快捷键?我应该把绑定放在哪里?

【问题讨论】:

  • 是的,我认为 InputBinding 是最好的方法。我会先尝试你的第三种方法。仅当定义它们的控件具有焦点时,才会捕获键。因此,如果您想为整个应用程序使用 InputBinding,则必须为窗口定义它。
  • @MightyBadaboom 那么 Visual Studio 呢?在我看来,VS 在堆栈中更高,并且会在调用 handle 之前比我的 Window 更快。
  • 你试过了还是不行?因为我猜它应该可以工作,因为该命令将从具有焦点的应用程序中处理。

标签: c# wpf xaml vsix envdte


【解决方案1】:

KeyBindings 看起来很复杂,需要在几个步骤中定义(也取决于要求)。此答案是对user1892538 答案的奖励。

场景:我们得到了已经显示的toolWindow,但是我们想添加一些命令,它会调用view/view-model中的方法。


1.创建新的Command步骤 3this 教程中):

右键单击项目 -> 添加New Item -> Custom command。这将创建 2 个文件并使用包修改文件:

  • CommandName.png - 菜单图标
  • CommandName.cs - 包含命令源代码的类文件
  • ProjectWindowPackage.cs - 带有Initialize()方法的包类,它调用CommandName.csInitialize()

MyWindowPackage.cs

public sealed class MyWindowPackage : Package
{
    public const string PackageGuidString = "00000000-0000-0000-0000-000000000003";

    public MyWindowPackage() { }

    protected override void Initialize()
    {
        MyToolWindowCommand.Initialize(this);
        MySaveCommand.Initialize(this);
        base.Initialize();
    }
}

CommandName.cs

// these 2 values will do the binding
public static readonly Guid ApplicationCommands
                                  = new Guid("00000000-0000-0000-0000-000000000002");
public const int SaveCommandId = 0x0201;

private readonly Package package;

private CommandName(Package package)
{
    // we need to have package (from Initialize() method) to set VS
    if (package == null) throw new ArgumentNullException("package");
    this.package = package;

    // this provides access for the Menu (so we can add our Command during init)
    OleMenuCommandService commandService = this.ServiceProvider.GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
    if (commandService != null)
    {
        // Creates new command "reference" (global ID)
        var menuCommandID = new CommandID(ApplicationCommands, SaveCommandId);
        // Create new command instance (method to invoke, ID of command)
        var menuItem = new MenuCommand(this.Save, menuCommandID);
        // Adding new command to the menu
        commandService.AddCommand(menuItem);
    }

    private void Save()
    {
        // Get instance of our window object (param false -> won't create new window)
        ToolWindowPane lToolWindow = this.package.FindToolWindow(typeof(MyToolWindow), 0, false);
        if ((null == lToolWindow) || (null == lToolWindow.Frame)) return;

        // Handle the toolWindow's content as Window (our control)
        ((lToolWindow as MyToolWindow)?.Content as MyWindowControl)?.Save();
    }
}

2。将 MyToolWindow 的内容设置为 MyWindowControl(在 VSIX 创建时完成):

MyToolWindow.cs

[Guid("00000000-0000-0000-0000-000000000001")] //GUID of ToolWindow
public class MyToolWindow : ToolWindowPane
{
    public MyToolWindow() : base(null)
    {
        this.Content = new MyWindowControl();
    }
}

3.在代码隐藏中设置代码以调用 ViewModel(或自己完成工作):

MyWindowControl.cs

public partial class MyWindowControl : UserControl
{
    // output omitted for brevity

    public void Save()
    {
        // Do the call towards view-model or run the code

        (this.DataContext as MyViewModel)?.SaveCmd.Execute(null);
    }
}

4.将 Command 设置为 Shortcut 以便 VS 知道如何处理它们:

MZTools' article 中可以找到解决方案如何添加Command 而不会在菜单中看到它,但是如果您转到工具-> 窗口-> 键盘,您可能会在那里找到它们(因此您可以设置快捷方式) .

我将同时显示原点Button(用于显示工具窗口)和第二个不可见的Button,仅用于快捷方式(Keybind)。

MyWindowPackage.vsct(分几部分):

<!-- shows the definition of commands/buttons in menu, Canonical name is how You can find the command in VS [Tools -> Keyboard -> CommandName] -->
<Commands package="guidMyWindowPackage">

    <Button guid="guidMyWindowPackageCmdSet"
            id="MyWindowCommandId"
            priority="0x0100"
            type="Button">
    <Parent guid="guidSHLMainMenu" id="IDG_VS_WNDO_OTRWNDWS1" />
    <Strings>
      <ButtonText>My ToolWindow</ButtonText>
      <CommandName>MyCommand</CommandName>
      <MenuText>My ToolWindow</MenuText>
      <LocCanonicalName>MyToolWindow</LocCanonicalName>
    </Strings>
  </Button>

  <Button guid="guidMyWindowPackageCmdSet"
          id="MySaveCommandId"
          priority="0x0100"
          type="Button">
    <Strings>
      <ButtonText>My ToolWindow Save</ButtonText>
      <LocCanonicalName>MyToolWindow.Save</LocCanonicalName>
    </Strings>
  </Button>
</Buttons>
</Commands>

KeyBindings(快捷键定义):

<KeyBindings>
    <KeyBinding guid="guidMyWindowPackageCmdSet"
                id="MySaveCommandId"
                editor="guidVSStd97"
                key1="1" mod1="Control" />
</KeyBindings>

还有Symbols,它将GUIDCommand definitionCommand logic设置并绑定在一起:

<Symbols>
    <!-- This is the package guid. -->
    <GuidSymbol name="guidMyWindowPackage" value="{00000000-0000-0000-0000-000000000003}" />

    <!-- This is the guid used to group the menu commands together -->
    <GuidSymbol name="guidMyWindowPackageCmdSet" value="{00000000-0000-0000-0000-000000000002}">
        <IDSymbol name="MyWindowCommandId" value="0x0100" />
        <IDSymbol name="MySaveCommandId" value="0x0201" />
    </GuidSymbol>

<!-- some more GuidSymbols -->

</Symbols>

奖励:

KeyBinding 确实有属性editor="guidVSStd97",这会将绑定范围设置为“GENERAL”(可在每个窗口中使用)。如果您可以将其设置为您的ToolWindowGUID,则仅在选择ToolWindow 时才会使用。它是如何工作的,描述为behind this link。要完成它,请访问this link

【讨论】:

  • 非常详细! thiseditor="guidWidgetEditor" 的例子呢?也看看这个answereditor="guidSourceCodeTextEditor"的例子......
  • 不过,这很好用。有没有办法让这个命令在工具 > 选项 > 环境 > 键盘下可见?
  • 文件MyWindowPackage.vsct (LocCanonicalName) 中指定的名称应该在选项菜单中可供您使用。检查答案中的 Key Bindings 部分,这就是为您创建键绑定的内容(您可以在选项表中找到)。
【解决方案2】:

你是对的,该快捷方式由默认的 Visual Studio 命令使用,该命令优先于扩展。

来自类似的msdn post,此行为已确认,建议选择不同的组合。

查找reference 以获取 VS 快捷方式的完整列表。快捷键适用于各种范围(例如,当您在文本编辑器中时,文本编辑器范围的快捷键优先于全局快捷键)。 除此之外,您可以customize 快捷方式的行为,还可以导入新的键盘映射方案并在 Tools > Options > Environment 下选择它> 键盘

.vsct 中的KeyBindings 部分是您可以将命令与键盘快捷键相关联的地方。 Microsoft 示例位于 github

【讨论】:

  • 非常感谢您的回答,我将奖励您赏金,但是我决定自己回答这个问题,因为我相信还有更多需要解释。干杯 =)
【解决方案3】:

user1892538 的好回答

另外,请注意某些快捷方式被操作系统或机器上运行的其他软件占用。

Ctrl+Esc 将激活 Windows 机器上的开始菜单。

其他示例: - Intel 图形软件接管 Ctrl+Alt+F8。 - 某些 Ctrl+Alt 组合可能无法通过远程桌面连接。

【讨论】:

    猜你喜欢
    • 2012-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多