Menambahkan pencarian ke jendela alat
Saat membuat atau memperbarui jendela alat di ekstensi, Anda dapat menambahkan fungsionalitas pencarian yang sama yang muncul di tempat lain di Visual Studio. Fungsionalitas ini mencakup fitur-fitur berikut:
Kotak pencarian yang selalu terletak di area kustom toolbar.
Indikator kemajuan yang dilapisi pada kotak pencarian itu sendiri.
Kemampuan untuk menampilkan hasil segera setelah Anda memasukkan setiap karakter (pencarian instan) atau hanya setelah Anda memilih tombol Enter (pencarian sesuai permintaan).
Daftar yang memperlihatkan istilah yang terakhir kali Anda cari.
Kemampuan untuk memfilter pencarian berdasarkan bidang atau aspek tertentu dari target pencarian.
Dengan mengikuti panduan ini, Anda akan mempelajari cara melakukan tugas berikut:
Buat proyek VSPackage.
Buat jendela alat yang berisi UserControl dengan TextBox baca-saja.
Tambahkan kotak pencarian ke jendela alat.
Tambahkan implementasi pencarian.
Aktifkan pencarian instan dan tampilan bilah kemajuan.
Tambahkan opsi Cocokkan kasus .
Tambahkan filter Cari bahkan baris saja.
Untuk membuat proyek VSIX
- Buat proyek VSIX bernama
TestToolWindowSearch
dengan jendela alat bernama TestSearch. Jika Anda memerlukan bantuan untuk melakukan ini, lihat Membuat ekstensi dengan jendela alat.
Untuk membuat jendela alat
TestToolWindowSearch
Dalam proyek, buka file TestSearchControl.xaml.Ganti blok yang ada
<StackPanel>
dengan blok berikut, yang menambahkan baca-saja TextBox ke UserControl di jendela alat.<StackPanel Orientation="Vertical"> <TextBox Name="resultsTextBox" Height="800.0" Width="800.0" IsReadOnly="True"> </TextBox> </StackPanel>
Dalam file TestSearchControl.xaml.cs, tambahkan yang berikut ini menggunakan direktif:
using System.Text;
button1_Click()
Hapus metode .Di kelas TestSearchControl, tambahkan kode berikut.
Kode ini menambahkan properti publik TextBox bernama SearchResultsTextBox dan properti string publik bernama SearchContent. Di konstruktor, SearchResultsTextBox diatur ke kotak teks, dan SearchContent diinisialisasi ke sekumpulan string yang dibatasi baris baru. Konten kotak teks juga diinisialisasi ke kumpulan string.
public partial class MyControl : UserControl { public TextBox SearchResultsTextBox { get; set; } public string SearchContent { get; set; } public MyControl() { InitializeComponent(); this.SearchResultsTextBox = resultsTextBox; this.SearchContent = BuildContent(); this.SearchResultsTextBox.Text = this.SearchContent; } private string BuildContent() { StringBuilder sb = new StringBuilder(); sb.AppendLine("1 go"); sb.AppendLine("2 good"); sb.AppendLine("3 Go"); sb.AppendLine("4 Good"); sb.AppendLine("5 goodbye"); sb.AppendLine("6 Goodbye"); return sb.ToString(); } }
Bangun proyek dan mulai penelusuran kesalahan. Instans eksperimental Visual Studio muncul.
Pada bilah menu, pilih Tampilkan>Windows>TestSearch Lainnya.
Jendela alat muncul, tetapi kontrol pencarian belum muncul.
Untuk menambahkan kotak pencarian ke jendela alat
Dalam file TestSearch.cs, tambahkan kode berikut ke
TestSearch
kelas . Kode mengambil alih SearchEnabled properti sehingga get accessor mengembalikantrue
.Untuk mengaktifkan pencarian, Anda harus mengambil alih SearchEnabled properti . Kelas ToolWindowPane mengimplementasikan IVsWindowSearch dan menyediakan implementasi default yang tidak mengaktifkan pencarian.
public override bool SearchEnabled { get { return true; } }
Bangun proyek dan mulai penelusuran kesalahan. Instans eksperimental muncul.
Dalam instans eksperimental Visual Studio, buka TestSearch.
Di bagian atas jendela alat, kontrol pencarian muncul dengan marka air Pencarian dan ikon kaca pembesar. Namun, pencarian belum berfungsi karena proses pencarian belum diimplementasikan.
Untuk menambahkan implementasi pencarian
Saat Anda mengaktifkan pencarian pada ToolWindowPane, seperti pada prosedur sebelumnya, jendela alat membuat host pencarian. Host ini menyiapkan dan mengelola proses pencarian, yang selalu terjadi pada utas latar belakang. ToolWindowPane Karena kelas mengelola pembuatan host pencarian dan pengaturan pencarian, Anda hanya perlu membuat tugas pencarian dan menyediakan metode pencarian. Proses pencarian terjadi pada utas latar belakang, dan panggilan ke kontrol jendela alat terjadi pada utas UI. Oleh karena itu, Anda harus menggunakan metode ThreadHelper.Invoke* untuk mengelola panggilan apa pun yang Anda lakukan dalam menangani kontrol.
Dalam file TestSearch.cs, tambahkan arahan berikut
using
:using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text; using System.Windows.Controls; using Microsoft.Internal.VisualStudio.PlatformUI; using Microsoft.VisualStudio; using Microsoft.VisualStudio.PlatformUI; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop;
TestSearch
Di kelas , tambahkan kode berikut, yang melakukan tindakan berikut:CreateSearch Mengambil alih metode untuk membuat tugas pencarian.
Mengambil alih ClearSearch metode untuk memulihkan status kotak teks. Metode ini dipanggil ketika pengguna membatalkan tugas pencarian dan ketika pengguna mengatur atau membatalkan pengaturan opsi atau filter. Keduanya CreateSearch dan ClearSearch dipanggil pada utas UI. Oleh karena itu, Anda tidak perlu mengakses kotak teks dengan metode ThreadHelper.Invoke* .
Membuat kelas bernama yang
TestSearchTask
mewarisi dari VsSearchTask, yang menyediakan implementasi default .IVsSearchTaskDi
TestSearchTask
, konstruktor mengatur bidang privat yang mereferensikan jendela alat. Untuk menyediakan metode pencarian, Anda mengambil alih OnStartSearch metode dan OnStopSearch . Metode OnStartSearch ini adalah tempat Anda menerapkan proses pencarian. Proses ini termasuk melakukan pencarian, menampilkan hasil pencarian di kotak teks, dan memanggil implementasi kelas dasar metode ini untuk melaporkan bahwa pencarian selesai.
public override IVsSearchTask CreateSearch(uint dwCookie, IVsSearchQuery pSearchQuery, IVsSearchCallback pSearchCallback) { if (pSearchQuery == null || pSearchCallback == null) return null; return new TestSearchTask(dwCookie, pSearchQuery, pSearchCallback, this); } public override void ClearSearch() { TestSearchControl control = (TestSearchControl)this.Content; control.SearchResultsTextBox.Text = control.SearchContent; } internal class TestSearchTask : VsSearchTask { private TestSearch m_toolWindow; public TestSearchTask(uint dwCookie, IVsSearchQuery pSearchQuery, IVsSearchCallback pSearchCallback, TestSearch toolwindow) : base(dwCookie, pSearchQuery, pSearchCallback) { m_toolWindow = toolwindow; } protected override void OnStartSearch() { // Use the original content of the text box as the target of the search. var separator = new string[] { Environment.NewLine }; TestSearchControl control = (TestSearchControl)m_toolWindow.Content; string[] contentArr = control.SearchContent.Split(separator, StringSplitOptions.None); // Get the search option. bool matchCase = false; // matchCase = m_toolWindow.MatchCaseOption.Value; // Set variables that are used in the finally block. StringBuilder sb = new StringBuilder(""); uint resultCount = 0; this.ErrorCode = VSConstants.S_OK; try { string searchString = this.SearchQuery.SearchString; // Determine the results. uint progress = 0; foreach (string line in contentArr) { if (matchCase == true) { if (line.Contains(searchString)) { sb.AppendLine(line); resultCount++; } } else { if (line.ToLower().Contains(searchString.ToLower())) { sb.AppendLine(line); resultCount++; } } // SearchCallback.ReportProgress(this, progress++, (uint)contentArr.GetLength(0)); // Uncomment the following line to demonstrate the progress bar. // System.Threading.Thread.Sleep(100); } } catch (Exception e) { this.ErrorCode = VSConstants.E_FAIL; } finally { ThreadHelper.Generic.Invoke(() => { ((TextBox)((TestSearchControl)m_toolWindow.Content).SearchResultsTextBox).Text = sb.ToString(); }); this.SearchResults = resultCount; } // Call the implementation of this method in the base class. // This sets the task status to complete and reports task completion. base.OnStartSearch(); } protected override void OnStopSearch() { this.SearchResults = 0; } }
Uji implementasi pencarian Anda dengan melakukan langkah-langkah berikut:
Bangun ulang proyek dan mulai penelusuran kesalahan.
Dalam instans eksperimental Visual Studio, buka jendela alat lagi, masukkan beberapa teks pencarian di jendela pencarian, dan klik ENTER.
Hasil yang benar akan muncul.
Untuk mengkustomisasi perilaku pencarian
Dengan mengubah pengaturan pencarian, Anda dapat membuat berbagai perubahan dalam bagaimana kontrol pencarian muncul dan bagaimana pencarian dilakukan. Misalnya, Anda dapat mengubah marka air (teks default yang muncul di kotak pencarian), lebar minimum dan maksimum kontrol pencarian, dan apakah akan menampilkan bilah kemajuan. Anda juga dapat mengubah titik di mana hasil pencarian mulai muncul (sesuai permintaan atau pencarian instan) dan apakah akan menampilkan daftar istilah yang baru-baru ini Anda cari. Anda dapat menemukan daftar lengkap pengaturan di SearchSettingsDataSource kelas .
Dalam file* TestSearch.cs*, tambahkan kode berikut ke
TestSearch
kelas . Kode ini memungkinkan pencarian instan alih-alih pencarian sesuai permintaan (yang berarti bahwa pengguna tidak perlu mengklik ENTER). Kode mengambil alihProvideSearchSettings
metode diTestSearch
kelas , yang diperlukan untuk mengubah pengaturan default.public override void ProvideSearchSettings(IVsUIDataSource pSearchSettings) { Utilities.SetValue(pSearchSettings, SearchSettingsDataSource.SearchStartTypeProperty.Name, (uint)VSSEARCHSTARTTYPE.SST_INSTANT);}
Uji pengaturan baru dengan membangun kembali solusi dan memulai ulang debugger.
Hasil pencarian muncul setiap kali Anda memasukkan karakter di kotak pencarian.
Dalam metode ,
ProvideSearchSettings
tambahkan baris berikut, yang memungkinkan tampilan bilah kemajuan.public override void ProvideSearchSettings(IVsUIDataSource pSearchSettings) { Utilities.SetValue(pSearchSettings, SearchSettingsDataSource.SearchStartTypeProperty.Name, (uint)VSSEARCHSTARTTYPE.SST_INSTANT); Utilities.SetValue(pSearchSettings, SearchSettingsDataSource.SearchProgressTypeProperty.Name, (uint)VSSEARCHPROGRESSTYPE.SPT_DETERMINATE); }
Agar bilah kemajuan muncul, kemajuan harus dilaporkan. Untuk melaporkan kemajuan, batalkan komentar kode berikut dalam
OnStartSearch
metodeTestSearchTask
kelas:SearchCallback.ReportProgress(this, progress++, (uint)contentArr.GetLength(0));
Agar pemrosesan cukup lambat sehingga bilah kemajuan terlihat, batalkan komentar baris berikut dalam
OnStartSearch
metodeTestSearchTask
kelas:System.Threading.Thread.Sleep(100);
Uji pengaturan baru dengan membangun kembali solusi dan mulai men-debug.
Bilah kemajuan muncul di jendela pencarian (sebagai garis biru di bawah kotak teks pencarian) setiap kali Anda melakukan pencarian.
Untuk memungkinkan pengguna menyempurnakan pencarian mereka
Anda dapat mengizinkan pengguna untuk menyempurnakan pencarian mereka dengan cara opsi seperti Cocokkan huruf besar/kecil atau Cocokkan seluruh kata. Opsi bisa boolean, yang muncul sebagai kotak centang, atau perintah, yang muncul sebagai tombol. Untuk panduan ini, Anda akan membuat opsi boolean.
Dalam file TestSearch.cs, tambahkan kode berikut ke
TestSearch
kelas . Kode mengambil alihSearchOptionsEnum
metode , yang memungkinkan implementasi pencarian untuk mendeteksi apakah opsi tertentu aktif atau nonaktif. Kode dalamSearchOptionsEnum
menambahkan opsi untuk mencocokkan kasus dengan IVsEnumWindowSearchOptions enumerator. Opsi untuk mencocokkan kasus juga tersedia sebagaiMatchCaseOption
properti .private IVsEnumWindowSearchOptions m_optionsEnum; public override IVsEnumWindowSearchOptions SearchOptionsEnum { get { if (m_optionsEnum == null) { List<IVsWindowSearchOption> list = new List<IVsWindowSearchOption>(); list.Add(this.MatchCaseOption); m_optionsEnum = new WindowSearchOptionEnumerator(list) as IVsEnumWindowSearchOptions; } return m_optionsEnum; } } private WindowSearchBooleanOption m_matchCaseOption; public WindowSearchBooleanOption MatchCaseOption { get { if (m_matchCaseOption == null) { m_matchCaseOption = new WindowSearchBooleanOption("Match case", "Match case", false); } return m_matchCaseOption; } }
TestSearchTask
Di kelas , batalkan komentar baris berikut dalamOnStartSearch
metode :matchCase = m_toolWindow.MatchCaseOption.Value;
Uji opsi:
Bangun proyek dan mulai penelusuran kesalahan. Instans eksperimental muncul.
Di jendela alat, pilih panah Bawah di sisi kanan kotak teks.
Kotak centang Cocokkan huruf besar/kecil muncul.
Pilih kotak centang Cocokkan kasus , lalu lakukan beberapa pencarian.
Untuk menambahkan filter pencarian
Anda dapat menambahkan filter pencarian yang memungkinkan pengguna menyempurnakan kumpulan target pencarian. Misalnya, Anda dapat memfilter file di File Explorer berdasarkan tanggal di mana file tersebut dimodifikasi baru-baru ini dan ekstensi nama filenya. Dalam panduan ini, Anda akan menambahkan filter hanya untuk garis genap. Saat pengguna memilih filter tersebut, host pencarian menambahkan string yang Anda tentukan ke kueri pencarian. Anda kemudian dapat mengidentifikasi string ini di dalam metode pencarian Anda dan memfilter target pencarian yang sesuai.
Dalam file TestSearch.cs, tambahkan kode berikut ke
TestSearch
kelas . Kode mengimplementasikanSearchFiltersEnum
dengan menambahkan WindowSearchSimpleFilter yang menentukan untuk memfilter hasil pencarian sehingga hanya baris genap yang muncul.public override IVsEnumWindowSearchFilters SearchFiltersEnum { get { List<IVsWindowSearchFilter> list = new List<IVsWindowSearchFilter>(); list.Add(new WindowSearchSimpleFilter("Search even lines only", "Search even lines only", "lines", "even")); return new WindowSearchFilterEnumerator(list) as IVsEnumWindowSearchFilters; } }
Sekarang kontrol pencarian menampilkan filter
Search even lines only
pencarian . Saat pengguna memilih filter, stringlines:"even"
muncul di kotak pencarian. Kriteria pencarian lainnya dapat muncul pada saat yang sama dengan filter. String pencarian mungkin muncul sebelum filter, setelah filter, atau keduanya.Dalam file TestSearch.cs, tambahkan metode berikut ke
TestSearchTask
kelas , yang ada diTestSearch
kelas . Metode ini mendukungOnStartSearch
metode , yang akan Anda ubah di langkah berikutnya.private string RemoveFromString(string origString, string stringToRemove) { int index = origString.IndexOf(stringToRemove); if (index == -1) return origString; else return (origString.Substring(0, index) + origString.Substring(index + stringToRemove.Length)).Trim(); } private string[] GetEvenItems(string[] contentArr) { int length = contentArr.Length / 2; string[] evenContentArr = new string[length]; int indexB = 0; for (int index = 1; index < contentArr.Length; index += 2) { evenContentArr[indexB] = contentArr[index]; indexB++; } return evenContentArr; }
TestSearchTask
Di kelas , perbaruiOnStartSearch
metode dengan kode berikut. Perubahan ini memperbarui kode untuk mendukung filter.protected override void OnStartSearch() { // Use the original content of the text box as the target of the search. var separator = new string[] { Environment.NewLine }; string[] contentArr = ((TestSearchControl)m_toolWindow.Content).SearchContent.Split(separator, StringSplitOptions.None); // Get the search option. bool matchCase = false; matchCase = m_toolWindow.MatchCaseOption.Value; // Set variables that are used in the finally block. StringBuilder sb = new StringBuilder(""); uint resultCount = 0; this.ErrorCode = VSConstants.S_OK; try { string searchString = this.SearchQuery.SearchString; // If the search string contains the filter string, filter the content array. string filterString = "lines:\"even\""; if (this.SearchQuery.SearchString.Contains(filterString)) { // Retain only the even items in the array. contentArr = GetEvenItems(contentArr); // Remove 'lines:"even"' from the search string. searchString = RemoveFromString(searchString, filterString); } // Determine the results. uint progress = 0; foreach (string line in contentArr) { if (matchCase == true) { if (line.Contains(searchString)) { sb.AppendLine(line); resultCount++; } } else { if (line.ToLower().Contains(searchString.ToLower())) { sb.AppendLine(line); resultCount++; } } SearchCallback.ReportProgress(this, progress++, (uint)contentArr.GetLength(0)); // Uncomment the following line to demonstrate the progress bar. // System.Threading.Thread.Sleep(100); } } catch (Exception e) { this.ErrorCode = VSConstants.E_FAIL; } finally { ThreadHelper.Generic.Invoke(() => { ((TextBox)((TestSearchControl)m_toolWindow.Content).SearchResultsTextBox).Text = sb.ToString(); }); this.SearchResults = resultCount; } // Call the implementation of this method in the base class. // This sets the task status to complete and reports task completion. base.OnStartSearch(); }
Uji kode Anda.
Bangun proyek dan mulai penelusuran kesalahan. Dalam instans eksperimental Visual Studio, buka jendela alat, lalu pilih panah Bawah pada kontrol pencarian.
Kotak centang Cocokkan huruf besar/kecil dan filter Cari bahkan baris saja muncul.
Pilih filter.
Kotak pencarian berisi baris:"even", dan hasil berikut muncul:
2 bagus
4 Bagus
6 Selamat Tinggal
Hapus
lines:"even"
dari kotak pencarian, pilih kotak centang Cocokkan huruf besar/kecil , lalu masukkang
di kotak pencarian.Hasil berikut muncul:
1 pergi
2 bagus
5 selamat tinggal
Pilih X di sisi kanan kotak pencarian.
Pencarian dibersihkan, dan konten asli muncul. Namun, kotak centang Cocokkan huruf masih dipilih.