ソリューション エクスプローラーのフィルターを拡張する
ソリューション エクスプローラー フィルター機能を拡張して、さまざまなファイルを表示または非表示にすることができます。 たとえば、このチュートリアルで示すように、ソリューション エクスプローラーに C# クラス ファクトリ ファイルのみを表示するフィルターを作成できます。
Visual Studio パッケージ プロジェクトを作成する
FileFilter
という名前の VSIX プロジェクトを作成します。 FileFilter という名前のカスタム コマンド項目テンプレートを追加します。 詳細については、「メニュー コマンドを使用した拡張機能の作成」を参照してください。System.ComponentModel.Composition
およびMicrosoft.VisualStudio.Utilities
への参照を追加します。メニュー コマンドがソリューション エクスプローラー ツールバーに表示されるようにします。 FileFilterPackage.vsct ファイルを開きます。
<Button>
ブロックを次のように変更します。<Button guid="guidFileFilterPackageCmdSet" id="FileFilterId" priority="0x0400" type="Button"> <Parent guid="guidSHLMainMenu" id="IDG_VS_TOOLBAR_PROJWIN_FILTERS" /> <Icon guid="guidImages" id="bmpPic1" /> <Strings> <ButtonText>FileNameFilter</ButtonText> </Strings> </Button>
マニフェスト ファイルを更新する
source.extension.vsixmanifest ファイルで、MEF コンポーネントであるアセットを追加します。
[資産] タブで [新規] ボタンを選択します。
[種類] フィールドで [Microsoft.VisualStudio.MefComponent] を選択します。
[ソース] フィールドで、[現在のソリューション内のプロジェクト] を選択します。
[プロジェクト] フィールドで [FileFilter] を選択し、[OK] をクリックします。
フィルター コードを追加する
いくつかの GUID を FileFilterPackageGuids.cs ファイルに追加します。
public const string guidFileFilterPackageCmdSetString = "00000000-0000-0000-0000-00000000"; // get your GUID from the .vsct file public const int FileFilterId = 0x100;
FileNameFilter.cs という名前の FileFilter プロジェクトにクラス ファイルを追加します。
空の名前空間と空のクラスを次のコードに置き換えます。
Task<IReadOnlyObservableSet> GetIncludedItemsAsync(IEnumerable<IVsHierarchyItem rootItems)
メソッドは、ソリューションのルート (rootItems
) を含むコレクションを受け取り、フィルターに含める項目のコレクションを返します。ShouldIncludeInFilter
メソッドは、指定した条件に基づいて、ソリューション エクスプローラー階層内の項目をフィルター処理します。using System; using System.Collections.Generic; using System.ComponentModel.Composition; using System.Text.RegularExpressions; using System.Threading.Tasks; using Microsoft.Internal.VisualStudio.PlatformUI; using Microsoft.VisualStudio.Shell; namespace FileFilter { // Implements ISolutionTreeFilterProvider. The SolutionTreeFilterProvider attribute declares it as a MEF component [SolutionTreeFilterProvider(FileFilterPackageGuids.guidFileFilterPackageCmdSetString, (uint)(FileFilterPackageGuids.FileFilterId))] public sealed class FileNameFilterProvider : HierarchyTreeFilterProvider { SVsServiceProvider svcProvider; IVsHierarchyItemCollectionProvider hierarchyCollectionProvider; // Constructor required for MEF composition [ImportingConstructor] public FileNameFilterProvider(SVsServiceProvider serviceProvider, IVsHierarchyItemCollectionProvider hierarchyCollectionProvider) { this.svcProvider = serviceProvider; this.hierarchyCollectionProvider = hierarchyCollectionProvider; } // Returns an instance of Create filter class. protected override HierarchyTreeFilter CreateFilter() { return new FileNameFilter(this.svcProvider, this.hierarchyCollectionProvider, FileNamePattern); } // Regex pattern for CSharp factory classes private const string FileNamePattern = @"\w*factory\w*(.cs$)"; // Implementation of file filtering private sealed class FileNameFilter : HierarchyTreeFilter { private readonly Regex regexp; private readonly IServiceProvider svcProvider; private readonly IVsHierarchyItemCollectionProvider hierarchyCollectionProvider; public FileNameFilter( IServiceProvider serviceProvider, IVsHierarchyItemCollectionProvider hierarchyCollectionProvider, string fileNamePattern) { this.svcProvider = serviceProvider; this.hierarchyCollectionProvider = hierarchyCollectionProvider; this.regexp = new Regex(fileNamePattern, RegexOptions.IgnoreCase); } // Gets the items to be included from this filter provider. // rootItems is a collection that contains the root of your solution // Returns a collection of items to be included as part of the filter protected override async Task<IReadOnlyObservableSet> GetIncludedItemsAsync(IEnumerable<IVsHierarchyItem> rootItems) { IVsHierarchyItem root = HierarchyUtilities.FindCommonAncestor(rootItems); IReadOnlyObservableSet<IVsHierarchyItem> sourceItems; sourceItems = await hierarchyCollectionProvider.GetDescendantsAsync( root.HierarchyIdentity.NestedHierarchy, CancellationToken); IFilteredHierarchyItemSet includedItems = await hierarchyCollectionProvider.GetFilteredHierarchyItemsAsync( sourceItems, ShouldIncludeInFilter, CancellationToken); return includedItems; } // Returns true if filters hierarchy item name for given filter; otherwise, false</returns> private bool ShouldIncludeInFilter(IVsHierarchyItem hierarchyItem) { if (hierarchyItem == null) { return false; } return this.regexp.IsMatch(hierarchyItem.Text); } } } }
FileFilter.cs で、FileFilter コンストラクターからコマンド配置および処理コードを削除します。 結果は次のようになります。
private FileFilter(Package package) { if (package == null) { throw new ArgumentNullException("package"); } this.package = package; }
ShowMessageBox()
メソッドも削除します。FileFilterPackage.cs で、
Initialize()
メソッド内のコードを次のコードに置き換えます。protected override void Initialize() { Debug.WriteLine (string.Format(CultureInfo.CurrentCulture, "Entering Initialize() of: {0}", this.ToString())); base.Initialize(); }
コードのテスト
プロジェクトをビルドして実行します。 Visual Studio の 2 番目のインスタンスが表示されます。 これは実験用インスタンスと呼ばれます。
Visual Studio の実験用インスタンスで、C# プロジェクトを開きます。
ソリューション エクスプローラー ツールバーで追加したボタンを探します。 左側から 4 番目のボタンになるはずです。
このボタンをクリックすると、すべてのファイルがフィルターで除外され、[ソリューション エクスプローラー] の [すべての項目がビューからフィルターされました。] が表示されます。