VSIX window - 执行 ICommand 的快捷键
VSIX window - key shortcut to execute ICommand
有一个 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正在保存文件)
- 我可能需要在封装
UserControl
的 Window
上设置绑定
- 我可能需要在
*Package.vsct
中设置绑定并将其路由,因为它将是 Visual Studio 中的 Command
问题:我应该如何绑定到快捷键?我应该把绑定放在哪里?
你说得对,默认的 Visual Studio 命令使用快捷方式, 优先于 扩展名。
从类似的 msdn post 中,此行为得到 确认,建议选择 不同的 组合。
查找 reference 以获得完整的 VS 快捷方式列表。快捷键适用于各种范围(例如,当您在文本编辑器中时,文本编辑器范围内的快捷键优先于全局快捷键)。
除此之外,您可以 customize 快捷方式的行为,还可以导入新的键盘映射方案并 select 它位于 Tools > Options > 环境 > 键盘.
.vsct 中的 KeyBindings
部分是您可以将命令与键盘快捷键相关联的地方。 Microsoft 样本在 github
KeyBindings
看起来很复杂,需要在几个步骤中定义(也取决于要求)。这个答案是作为对 .
答案的奖励而写的
场景: 我们得到了已经显示的工具Window,但我们想添加一些命令,它将调用view/view-model 中的方法。
1.创建新的 Command
(步骤 3 在 this 教程中):
右键单击项目 -> 添加 New Item
-> Custom command
。这将创建 2 个文件并使用包修改文件:
CommandName.png
- 菜单图标
CommandName.cs
- class 包含命令源代码的文件
ProjectWindowPackage.cs
- Package class with Initialize()
方法,调用 Initialize()
of CommandName.cs
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
而不在菜单中看到它的解决方案,但是如果您转到工具->Window->键盘,您可能会发现他们在那里(所以你可以设置快捷方式)。
我将同时显示原点 Button
(用于显示工具 window)和仅用于快捷方式(Keybind
)的第二个不可见 Button
。
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
,它们将 GUID
、Command definition
和 Command 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"(可在每个 window 中使用)。如果You can set this to the GUID
of Your ToolWindow
,它只会在选择ToolWindow
时使用。 . And to acomplish it full, get to this link.
描述了它是如何工作的
用户 1892538 的回答很好
另外,请注意操作系统或计算机上的其他软件 运行 会使用某些快捷方式。
Ctrl+Esc 将在 Windows 台机器上激活开始菜单。
其他例子:
- 英特尔图形软件接管 Ctrl+Alt+F8。
- 某些 Ctrl+Alt 组合可能无法通过远程桌面连接。
有一个 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正在保存文件)
- 我可能需要在封装
UserControl
的 - 我可能需要在
*Package.vsct
中设置绑定并将其路由,因为它将是 Visual Studio 中的
Window
上设置绑定
Command
问题:我应该如何绑定到快捷键?我应该把绑定放在哪里?
你说得对,默认的 Visual Studio 命令使用快捷方式, 优先于 扩展名。
从类似的 msdn post 中,此行为得到 确认,建议选择 不同的 组合。
查找 reference 以获得完整的 VS 快捷方式列表。快捷键适用于各种范围(例如,当您在文本编辑器中时,文本编辑器范围内的快捷键优先于全局快捷键)。 除此之外,您可以 customize 快捷方式的行为,还可以导入新的键盘映射方案并 select 它位于 Tools > Options > 环境 > 键盘.
.vsct 中的 KeyBindings
部分是您可以将命令与键盘快捷键相关联的地方。 Microsoft 样本在 github
KeyBindings
看起来很复杂,需要在几个步骤中定义(也取决于要求)。这个答案是作为对
场景: 我们得到了已经显示的工具Window,但我们想添加一些命令,它将调用view/view-model 中的方法。
1.创建新的 Command
(步骤 3 在 this 教程中):
右键单击项目 -> 添加 New Item
-> Custom command
。这将创建 2 个文件并使用包修改文件:
CommandName.png
- 菜单图标CommandName.cs
- class 包含命令源代码的文件ProjectWindowPackage.cs
- Package class withInitialize()
方法,调用Initialize()
ofCommandName.cs
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
而不在菜单中看到它的解决方案,但是如果您转到工具->Window->键盘,您可能会发现他们在那里(所以你可以设置快捷方式)。
我将同时显示原点 Button
(用于显示工具 window)和仅用于快捷方式(Keybind
)的第二个不可见 Button
。
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
,它们将 GUID
、Command definition
和 Command 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"(可在每个 window 中使用)。如果You can set this to the GUID
of Your ToolWindow
,它只会在选择ToolWindow
时使用。
用户 1892538 的回答很好
另外,请注意操作系统或计算机上的其他软件 运行 会使用某些快捷方式。
Ctrl+Esc 将在 Windows 台机器上激活开始菜单。
其他例子: - 英特尔图形软件接管 Ctrl+Alt+F8。 - 某些 Ctrl+Alt 组合可能无法通过远程桌面连接。