ソリューション エクスプローラーのフィルター機能を拡張して、異なるファイルの表示と非表示を切り替えることができます。 たとえば、このチュートリアルで示すように、 ソリューション エクスプローラーで 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] ボタンをクリックします。
フィルター コードを追加する
FileFilterPackageGuids.cs ファイルにいくつかの GUID を追加します。
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 番目のボタンである必要があります。
ボタンをクリックすると、すべてのファイルがフィルター処理され、 すべての項目がビューからフィルター処理されている ことがわかります。 ソリューション エクスプローラーで確認できます。