VSX是VS擴展,可以針對不同項目編寫插件,雖然接觸VSX的時間並不多,但是當了解VSX後深刻感受到VSX的魅力。
VSX的材料比較少,配置文件也很繁瑣,當初我也走了不少彎路。
這篇文章將幫助您更好的管理Package文件(繼承Package、注冊命令的那個文件),想要理解這篇文章您應當對VSX有基礎的了解,確保自己可以建立一個基礎的VSX菜單,如果目前您還不了解VSX也沒關系,我推薦您先閱讀明年我18的文章。
看過基礎材料後,感覺Package文件的內容真是多,包括初始化、注冊控件、菜單過濾、回調,就算把菜單過濾和回調挪走,一個典型的注冊命令代碼也有這麼多:
1 OleMenuCommand cmdidFindInSolutionExplorer = new OleMenuCommand(FindInSolutionExplorerCallback, 2 new CommandID(GuidList.guidConvenientCmdSet, (int)PkgCmdIDList.cmdidFindInSolutionExplorer)); 3 cmdidFindInSolutionExplorer.BeforeQueryStatus += new EventHandler(MenuFilter.ClinicalFilter); 4 mcs.AddCommand(cmdidFindInSolutionExplorer);
隨著插件功能的豐富,百十來個命令讓Package文件擁擠不堪,再加上過濾和回調,每次打開這個文件都頭皮發麻,(就算把回調和過濾分離成單獨文件,大批的回調和過濾函數也。。。)。
下面的解決方案可以讓你優雅的注冊命令,是讀codemaid源碼時學到的:
首先定義一個抽象類BaseCommand繼承OleMenuCommand,並在BaseCommand下定義兩個事件OnBeforeQueryStatus與OnExecute分別對應過濾和回調:
1 private static void BaseCommand_BeforeQueryStatus(object sender, EventArgs e)
2 {
3 BaseCommand command = sender as BaseCommand;
4 if (command != null)
5 {
6 command.OnBeforeQueryStatus();
7 }
8 }
9 protected virtual void OnBeforeQueryStatus()
10 {
11 Enabled = true;
12 }
13 private static void BaseCommand_Execute(object sender, EventArgs e)
14 {
15 BaseCommand command = sender as BaseCommand;
16 if (command != null)
17 {
18 command.OnExecute();
19 }
20 }
21 protected virtual void OnExecute()
22 {
23 }
在構造函數中注冊事件:
1 protected ClinicalVSXPackage Pkg { get; private set; }
2
3 protected BaseCommand(ClinicalVSXPackage pkg, CommandID id)
4 : base(BaseCommand_Execute, id)
5 {
6 Pkg = pkg;
7 BeforeQueryStatus += BaseCommand_BeforeQueryStatus;
8 }
Pkg是將Package類本身傳進來,方便傳遞dte等成員。
這樣就可以在Package文件中優雅的注冊命令了:
1 private readonly ICollection<BaseCommand> _commands = new List<BaseCommand>();
2
3 private void RegisterCommands()
4 {
5 var mcs = MenuCommandService;
6 if (null == mcs)
7 return;
8 _commands.Add(new 命令1(this));
9 _commands.Add(new 命令2(this));
10 _commands.Add(new 命令3this));
11 ....
12 foreach (var command in _commands)
13 mcs.AddCommand(command);
14 }
這樣當你打算新建一個命令,需要添加一個獨立的類繼承剛才的BaseCommand
並實現過濾和回調事件,一個典型的命令類:
1 internal class 命令1 : BaseCommand
2 {
3 public 命令1(Package pkg)
4 : base(pkg, new CommandID(CmdSetID, (int)PkgCmdIDList.命令ID))
5 { }
6
7 protected override void OnBeforeQueryStatus()
8 {
9 }
10 protected override void OnExecute()
11 {
12 base.OnExecute();
13 }
14 }