Перейти к содержимому

Как сделать поиск в wpf

  • автор:

Как сделать поиск в wpf

DataGrid во многом похож на ListView, но более сложный по характеру и допускает редактирование содержимого таблицы.

В разделе о ListView мы создали класс Phone, объекты которого выводили в список:

public class Phone < public string Title < get; set; >public string Company < get; set; >public int Price < get; set; >>

Теперь же выведем объекты в таблицу DataGrid. Чтобы DataGrid автоматически разбивал таблицу на столбцы, установим свойство AutoGenerateColumns=»True» :

В данном случае префикс local ссылается на пространство имен текущего проекта, в котором определен класс Phone (xmlns:local=»clr-namespace:Controls»), а col — префикс-ссылка на пространство имен System.Collections (xmlns:col=»clr-namespace:System.Collections;assembly=mscorlib»). И это даст в итоге следующий вывод:

Элемент DataGrid в WPF

Программная установка источника для DataGrid:

List phonesList = new List < new Phone < Title="iPhone 6S", Company="Apple", Price=54990 >, new Phone , new Phone >; phonesGrid.ItemsSource = phonesList;
Некоторые полезные свойства DataGrid

RowBackground и AlternatingRowBackground

Устанавливают фон строки. Если установлены оба свойства, цветовой фон чередуется: RowBackground — для нечетных строк и AlternatingRowBackground — для четных

Устанавливает высоту строки названий столбцов.

Устанавливает ширину столбцов.

Устанавливает высоту строк.

Устанавливает видимость линий, разделяющих столбцы и строки. Имеет четыре значения — All — видны все линии, Horizontal — видны только горизонтальные линии, Vertical — видны только вертикальные линии, None — линии отсутствуют

Задает видимость заголовков

HorizontalGridLinesBrush и VerticalGridLinesBrush

Задает цвет горизонтальных и вертикальных линий соответственно

Хотя предыдущий пример довольно прост, в нем есть несколько недочетов. Во-первых, у нас нет возможности повлиять на расстановку столбцов. Во-вторых, заголовки определены по названиям свойств, которые на английском языке, а хотелось бы на русском. В этом случае мы должны определить свойства отображения столбцов сами. Для этого надо воспользоваться свойством DataGrid.Columns и определить коллекцию столбцов для отображения в таблице.

Причем можно задать также и другой тип столбца, отличный от текстового. DataGrid поддерживает следующие варианты столбцов:

Отображает элемент TextBlock или TextBox при редактировании

Представляет гиперссылку и позволяет переходить по указанному адресу

Отображает элемент CheckBox

Отображает выпадающий список — элемент ComboBox

Позволяет задать специфичный шаблон для отображения столбца

Перепишем предыдущий пример с учетом новой информации:

      " Width="90" /> " Width="80" /> " Width="50" />  

Среди свойств DataGrid одним из самых интересных является RowDetailsTemplate . Оно позволяет задать шаблон отображения дополнительной информации касательно данной строки. Измени элемент DataGrid:

      " Width="90" /> " Width="80" /> " Width="50" />   " />     

Добавление поиска в окно инструментов

Область применения:yesVisual Studio Visual Studio для Mac noVisual Studio Code no

При создании или обновлении окна инструментов в расширении можно добавить ту же функцию поиска, которая отображается в другом месте Visual Studio. Эта функция включает следующие функции:

  • Поле поиска, которое всегда находится в пользовательской области панели инструментов.
  • Индикатор хода выполнения, наложенный на само поле поиска.
  • Возможность отображать результаты сразу после ввода каждого символа (мгновенного поиска) или только после выбора клавиши ВВОД (поиск по запросу).
  • Список, в котором показаны термины, для которых вы выполнили поиск в последнее время.
  • Возможность фильтрации поиска по определенным полям или аспектам целевых объектов поиска.

Следуя этому пошаговому руководству, вы узнаете, как выполнять следующие задачи:

  1. Создайте проект VSPackage.
  2. Создайте окно средства, содержащее UserControl с текстовым полем только для чтения.
  3. Добавьте поле поиска в окно инструментов.
  4. Добавьте реализацию поиска.
  5. Включите мгновенный поиск и отображение индикатора выполнения.
  6. Добавьте параметр «Вариант сопоставления».
  7. Добавьте только фильтр только строк поиска.

Создание проекта VSIX

  1. Создайте проект VSIX с именем TestToolWindowSearch окна инструментов с именем TestSearch. Если вам нужна помощь в этом, см. статью «Создание расширения с помощью окна инструментов».

Создание окна средства

  1. TestToolWindowSearch В проекте откройте файл TestSearchControl.xaml.
  2. Замените существующий блок следующим блоком, который добавляет доступ только для TextBoxUserControl чтения в окно инструментов.
using System.Text; 
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(); >> 
Partial Public Class MyControl Inherits System.Windows.Controls.UserControl Public Property SearchResultsTextBox As System.Windows.Controls.TextBox Public Property SearchContent As String Public Sub New() ' This call is required by the designer. InitializeComponent() ' Add any initialization after the InitializeComponent() call. Me.SearchResultsTextBox = resultsTextBox Me.SearchContent = buildContent Me.SearchResultsTextBox.Text = Me.SearchContent End Sub Private Function BuildContent() As String Dim sb As New System.Text.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() End Function End Class 

Добавление поля поиска в окно инструментов

  1. В файле TestSearch.cs добавьте следующий код в TestSearch класс. Код переопределяет SearchEnabled свойство, чтобы метод доступа возвращал true . Чтобы включить поиск, необходимо переопределить SearchEnabled свойство. Класс ToolWindowPane реализует IVsWindowSearch и предоставляет реализацию по умолчанию, которая не включает поиск.
public override bool SearchEnabled < get < return true; >> 

Добавление реализации поиска

При включении поиска по объекту ToolWindowPane,как и в предыдущей процедуре, окно инструментов создает узел поиска. Этот узел настраивает и управляет процессами поиска, которые всегда происходят в фоновом потоке. ToolWindowPane Так как класс управляет созданием узла поиска и настройкой поиска, необходимо создать только задачу поиска и предоставить метод поиска. Процесс поиска происходит в фоновом потоке и вызовы элемента управления окном инструментов происходят в потоке пользовательского интерфейса. Поэтому необходимо использовать метод ThreadHelper.Invoke* для управления вызовами, которые вы выполняете в работе с элементом управления.

    В файле TestSearch.cs добавьте следующие 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; 
  • Переопределяет CreateSearch метод для создания задачи поиска.
  • Переопределяет ClearSearch метод для восстановления состояния текстового поля. Этот метод вызывается, когда пользователь отменяет задачу поиска, а также когда пользователь задает или отменяет параметры или фильтры. ClearSearch Оба CreateSearch и вызываются в потоке пользовательского интерфейса. Поэтому доступ к текстовому поле не требуется с помощью метода ThreadHelper.Invoke* .
  • Создает класс, который TestSearchTask наследует от VsSearchTask, который предоставляет реализацию IVsSearchTaskпо умолчанию. В TestSearchTask конструкторе устанавливается частное поле, которое ссылается на окно инструментов. Чтобы предоставить метод поиска, переопределите OnStartSearch методы и OnStopSearch методы. Метод заключается в OnStartSearch реализации процесса поиска. Этот процесс включает выполнение поиска, отображение результатов поиска в текстовом поле и вызов реализации базового класса этого метода, чтобы сообщить о завершении поиска.
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; >> 
  1. Перестройте проект и запустите отладку.
  2. В экспериментальном экземпляре Visual Studio снова откройте окно инструментов, введите текст поиска в окне поиска и нажмите клавишу ВВОД. Должны отображаться правильные результаты.

Настройка поведения поиска

Изменив параметры поиска, можно внести различные изменения в способе отображения элемента управления поиском и способах выполнения поиска. Например, можно изменить подложку (текст по умолчанию, отображаемый в поле поиска), минимальную и максимальную ширину элемента управления поиска и показать ли индикатор выполнения. Вы также можете изменить точку, в которой результаты поиска начинают отображаться (по запросу или мгновенному поиску) и отображать список терминов, для которых вы недавно искали. Полный список параметров можно найти в SearchSettingsDataSource классе.

    В файле TestSearch.cs* добавьте следующий код в TestSearch класс. Этот код включает мгновенный поиск вместо поиска по запросу (это означает, что пользователю не нужно щелкнуть ВВОД). Код переопределяет ProvideSearchSettings метод в TestSearch классе, который необходим для изменения параметров по умолчанию.

public override void ProvideSearchSettings(IVsUIDataSource pSearchSettings)
public override void ProvideSearchSettings(IVsUIDataSource pSearchSettings)

Чтобы появилась панель выполнения, необходимо сообщить о ходе выполнения. Чтобы сообщить о ходе выполнения, раскомментируйте следующий код в OnStartSearch методе TestSearchTask класса:

SearchCallback.ReportProgress(this, progress++, (uint)contentArr.GetLength(0)); 
System.Threading.Thread.Sleep(100); 

Чтобы пользователи могли уточнить свои поисковые запросы

Вы можете разрешить пользователям уточнять поисковые запросы с помощью таких параметров, как «Совпадение» или «Совпадение всего слова«. Параметры могут быть логическими, которые отображаются как проверка поля или команды, которые отображаются в виде кнопок. В этом пошаговом руководстве вы создадите логический параметр.

    В файле TestSearch.cs добавьте следующий код в TestSearch класс. Код переопределяет SearchOptionsEnum метод, который позволяет реализации поиска определить, включен или отключен заданный параметр. В коде SearchOptionsEnum добавляется параметр сопоставления регистра IVsEnumWindowSearchOptions перечислителю. Вариант сопоставления регистра также доступен в качестве MatchCaseOption свойства.

private IVsEnumWindowSearchOptions m_optionsEnum; public override IVsEnumWindowSearchOptions SearchOptionsEnum < get < if (m_optionsEnum == null) < Listlist = new List(); 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; > > 
matchCase = m_toolWindow.MatchCaseOption.Value; 
  1. Выполните сборку решения и запустите отладку. Откроется экспериментальный экземпляр.
  2. В окне инструментов щелкните стрелку ВНИЗ в правой части текстового поля. Появится поле «Совпадение » проверка.
  3. Выберите поле «Совпадение» проверка поле, а затем выполните некоторые поиски.

Добавление фильтра поиска

Можно добавить фильтры поиска, позволяющие пользователям уточнить набор целевых объектов поиска. Например, файлы можно фильтровать в проводник по датам, в которых они были изменены в последнее время, и их расширения имени файла. В этом пошаговом руководстве вы добавите фильтр только для даже строк. Когда пользователь выбирает этот фильтр, узел поиска добавляет строки, указанные в запросе поиска. Затем эти строки можно определить внутри метода поиска и отфильтровать целевые объекты поиска соответствующим образом.

    В файле TestSearch.cs добавьте следующий код в TestSearch класс. Код реализуется SearchFiltersEnum путем добавления, WindowSearchSimpleFilter указывающего фильтрацию результатов поиска таким образом, чтобы отображались только даже строки.

public override IVsEnumWindowSearchFilters SearchFiltersEnum < get < Listlist = new List(); list.Add(new WindowSearchSimpleFilter("Search even lines only", "Search even lines only", "lines", "even")); return new WindowSearchFilterEnumerator(list) as IVsEnumWindowSearchFilters; > > 
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; > 
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(); > 

Фильтрация данных в элементе ListView

Мы уже совершали несколько различных задач вместе с ListView, как группировка и сортировка, но существует и другая очень важная возможность — фильтрация. Очевидно, что Вы могли бы ограничить количество элементов, которое могли бы добавить в первую очередь, но часто Вам нужно фильтровать ListView динамично, во время выполнения, обычно, основываясь на пользовательской строки фильтрации. К счастью для нас, механизмы view элемента ListView также позволяют с лёгкостью это выполнить, как мы наблюдали в случае сортировки и группировки.

Фильтрацию довольно просто выполнить, так что давайте перейдём прямиком к примеру и позже его обсудим:

using System; using System.Collections.Generic; using System.Windows; using System.Windows.Data; namespace WpfTutorialSamples.ListView_control < public partial class FilteringSample : Window < public FilteringSample() < InitializeComponent(); Listitems = new List(); items.Add(new User() < Name = "John Doe", Age = 42 >); items.Add(new User() < Name = "Jane Doe", Age = 39 >); items.Add(new User() < Name = "Sammy Doe", Age = 13 >); items.Add(new User() < Name = "Donna Doe", Age = 13 >); lvUsers.ItemsSource = items; CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(lvUsers.ItemsSource); view.Filter = UserFilter; > private bool UserFilter(object item) < if(String.IsNullOrEmpty(txtFilter.Text)) return true; else return ((item as User).Name.IndexOf(txtFilter.Text, StringComparison.OrdinalIgnoreCase) >= 0); > private void txtFilter_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e) < CollectionViewSource.GetDefaultView(lvUsers.ItemsSource).Refresh(); >> public enum SexType < Male, Female >; public class User < public string Name < get; set; >public int Age < get; set; >public string Mail < get; set; >public SexType Sex < get; set; >> >

Часть с XAML довольна проста: мы имеем TextBox, где пользователь может ввести значение поиска, и ListView для отображения результата.

В программной части мы начинаем с добавления нескольких User объектов в ListView так же, как мы делали в предыдущих примерах. Интересующая нас часть начинается в последних двух строках конструктора, где вы приобретаем ссылку на экземпляр CollectionView для ListView и далее назначаем делегат свойству Filter. Этот делегат указывает на функцию, названную UserFilter, которую мы реализовали ниже. Она обрабатывает каждый элемент, указанный в первом(и только) параметре и возвращает результат в виде логического значения, указывающего на то, должен ли данный элемент быть виден в списке.

В методе UserFilter() мы смотрим на элемент TextBox(txtFilter), чтобы увидеть содержит ли он любой текст — и если содержит, мы используем его для проверки содержания имени User(что является свойством, которое мы решили фильтровать) в введённой строке и возвращаем положительный или отрицательный результат в зависимости от его значения. Если TextBox пуст, то возвращаем true, так как в этом случае мы хотим, чтобы все элементы были видимы.

Событие txtFilter_TextChanged также важно. При каждом изменении текста мы получаем ссылку на объект View элемента ListView и далее на нём вызываем метод Refresh(). Это гарантирует точное срабатывание делегата Filter при каждом изменении значения строки поиска/фильтра в поле ввода пользователем.

Заключение

Это была довольно простая реализация, но с того момента, как Вы получите доступ ко всем элементам(в этом случае это класс User) вы сможете выполнять любые типы фильтрации какие захотите, так как Вы имеете полный доступ ко всей информации о каждом элементе в списке. Например, образец выше может быть легко изменён для фильтрации по возрасту, учитывающего свойство Age вместо свойства Name, или же Вы могли бы изменить его таким образом, чтобы учитывалось более одного свойства, например, для фильтрации пользователей в возрастом ниже X И с именем, которое не содержит «Y».

This article has been fully translated into the following languages:

Is your preferred language not on the list? Click here to help us translate this article into your language!

Учебник. Создание приложения WPF с помощью .NET

Из этого краткого руководства вы узнаете, как создать приложение Windows Presentation Foundation (WPF) с помощью Visual Studio. После создания первоначального приложения вы научитесь добавлять элементы управления и обрабатывать события. По завершении работы с этим руководством у вас будет простое приложение, добавляющее имена в список.

Документация по рабочему столу для .NET 7 и .NET 6 находится в стадии разработки.

В этом руководстве описано следующее:

  • Создание приложения WPF
  • Добавление элементов управления на форму
  • Обработка событий элемента управления для предоставления функциональных возможностей приложения
  • Выполнить приложение

Ниже представлен предварительный просмотр приложения, которое будет создано в данном руководстве.

Finished sample app for WPF tutorial

Необходимые компоненты

  • Visual Studio 2022 версии 17.0 или более поздней.
    • Выберите рабочую нагрузку Разработка классических приложений .NET.
    • Выберите отдельный компонент .NET 6.
    • Visual Studio 2022 версии 17.4 или более поздней версии
      • Выберите рабочую нагрузку Разработка классических приложений .NET.
      • Выберите отдельный компонент .NET 7

      Используйте Visual Studio 2022 версии 17.4 или более поздней версии и установите отдельные компоненты .NET 7 и .NET 6. Добавлена поддержка .NET 7 в Visual Studio 2022 версии 17.4.

      Создание приложения WPF

      Первым шагом в создании нового приложения является запуск Visual Studio и создание приложения на основе шаблона.

      Create a new WPF project in Visual Studio 2022 for .NET. 6

      1. Откройте Visual Studio.
      2. Выберите Создать новый проект.
      3. В поле Поиск шаблонов введите wpf и нажмите клавишу ВВОД .
      4. В раскрывающемся списке язык кода выберите C# или Visual Basic.
      5. В списке шаблонов выберите Приложение WPF, а затем нажмите Далее.

      Важно! Не выбирайте шаблон WPF Application (.NET Framework).

      Search for the WPF template in Visual Studio 2022 for .NET. 6

      На следующем рисунке показаны шаблоны проектов как для C#, так и для Visual Basic .NET. Если применить фильтр языка кода, отображается соответствующий шаблон.

    • В окне Настройка нового проекта выполните следующие действия:
      1. В поле Имя проекта введите Names.
      2. Установите флажок Разместить решение и проект в одном каталоге.
      3. При необходимости выберите другое расположение для сохранения кода.
      4. Нажмите кнопку Далее.

      Configure new WPF project in Visual Studio 2022 for .NET 6

      Select target framework for new WPF project in Visual Studio 2022 for .NET 6

    • На странице Дополнительные сведения выберите .NET 6.0 (долгосрочная поддержка) в поле Требуемая версия .NET Framework. Выберите кнопку Создать.
    • Create a new WPF project in Visual Studio 2022 for .NET 7.

      1. Откройте Visual Studio.
      2. Выберите Создать новый проект.
      3. В поле Поиск шаблонов введите wpf и нажмите клавишу ВВОД .
      4. В раскрывающемся списке язык кода выберите C# или Visual Basic.
      5. В списке шаблонов выберите Приложение WPF, а затем нажмите Далее.

      Важно! Не выбирайте шаблон WPF Application (.NET Framework).

      Search for the WPF template in Visual Studio 2022 for .NET. 7

      На следующем рисунке показаны шаблоны проектов как для C#, так и для Visual Basic .NET. Если применить фильтр языка кода, отображается соответствующий шаблон.

    • В окне Настройка нового проекта выполните следующие действия:
      1. В поле Имя проекта введите Names.
      2. Установите флажок Разместить решение и проект в одном каталоге.
      3. При необходимости выберите другое расположение для сохранения кода.
      4. Нажмите кнопку Далее.

      Configure new WPF project in Visual Studio 2022 for .NET 7

      Select target framework for new WPF project in Visual Studio 2022 for .NET 7

    • В окне дополнительных сведений выберите .NET 7.0 (стандартная поддержка терминов) для Target Framework. Выберите кнопку Создать.
    • После создания приложения в Visual Studio должна открыться панель конструктора XAML для формы по умолчанию MainWindow. Если конструктор не отображается, дважды щелкните файл MainWindow.xaml в области Обозреватель решений, чтобы открыть конструктор.

      Важные элементы среды Visual Studio

      Поддержка WPF в Visual Studio состоит из пяти важных компонентов, с которыми вы будете взаимодействовать при создании приложения.

      The important components of Visual Studio you should know when creating a WPF project for .NET

      1. Обозреватель решений Все файлы проекта, код, окна и ресурсы отображаются в этой области.
      2. Свойства На этой панели отображаются параметры свойств, которые можно настроить в зависимости от выбранного элемента. Например, если выбрать элемент в Обозревателе решений, отобразятся параметры свойств, связанные с файлом. Если выбрать объект в конструкторе, отобразятся параметры этого элемента.
      3. Панель инструментов Панель элементов содержит все элементы управления, которые можно добавить на форму. Чтобы добавить элемент управления на текущую форму, дважды щелкните элемент управления или перетащите его.
      4. Конструктор XAML Это конструктор для документа XAML. Он является интерактивным, и на него можно перетаскивать объекты из панели элементов. Выбирая и перемещая элементы в конструкторе, можно визуально создавать пользовательский интерфейс для приложения. Если конструктор и редактор отображаются, изменения в одном из них сразу отражаются в другом. При выборе элементов в конструкторе в области Свойства отображаются свойства и атрибуты этого объекта.
      5. Редактор кода XAML Это редактор кода XAML для документа XAML. Редактор кода XAML — это способ создания пользовательского интерфейса вручную без конструктора. Конструктор может вычислять значения свойств элемента управления при его добавлении в конструктор. В редакторе кода XAML вам предоставляется гораздо больше контроля. Если конструктор и редактор отображаются, изменения в одном из них сразу отражаются в другом. При переходе по текстовым курсорам в редакторе кода в области Свойства отображаются свойства и атрибуты этого объекта.

      Изучение кода XAML

      После создания проекта в редакторе кода XAML отображается минимальный объем кода XAML для отображения окна. Если редактор не открыт, дважды щелкните элемент MainWindow.xaml в обозревателе решений. Должен отобразиться код XAML, аналогичный следующему примеру:

      Давайте развернем этот код XAML, чтобы лучше понять его. XAML — это просто XML, который может обрабатываться компиляторами, используемыми в WPF. Он описывает пользовательский интерфейс WPF и взаимодействует с кодом .NET. Для понимания XAML следует, как минимум, знать основы XML.

      Корень документа представляет тип объекта, описываемого файлом XAML. Объявлено восемь атрибутов, и обычно они относятся к трем категориям:

      • Пространства имен Пространство имен XML предоставляет структуру языку XML, которая определяет содержимое, которое можно объявить в файле. Основной атрибут xmlns импортирует пространство имен XML для всего файла, а в данном случае сопоставляется с типами, объявленными в WPF. Другие пространства имен XML объявляют префикс и импортируют другие типы и объекты для XAML-файла. Например, пространство имен xmlns:local объявляет префикс local и выполняет сопоставление объектов, объявленных в проекте, с теми, которые объявлены в пространстве имен кода Names .
      • Атрибут x:Class Этот атрибут сопоставляет с типом, определенным в коде: файл MainWindow.xaml.cs или MainWindow.xaml.vb, который является классом Names.MainWindow .
      • Атрибут Title Любой обычный атрибут, объявленный в объекте XAML, задает свойство этого объекта. В этом случае атрибут Title задает свойство Window.Title .

      Изменение окна

      Сначала выполним проект и просмотрим выходные данные по умолчанию. Появится окно с заголовком MainWindow без элементов управления:

      A blank WPF app

      Для нашего примера приложения это окно слишком велико, а его заголовок не является описательным. Измените заголовок и размер окна, заменив соответствующие атрибуты в XAML следующими значениями:

      Подготовка макета

      В WPF имеется система макетов с широкими возможностями с множеством различных элементов управления макетом. Элементы управления макета помогают размещать дочерние элементы управления и изменять их размеры, а также могут даже это делать автоматически. Элемент управления макета по умолчанию, предоставляемый вам в этом XAML, — это элемент управления .

      Элемент управления Grid позволяет определить строки и столбцы, почти как в таблице, и размещать элементы управления внутри границ определенной комбинации строк и столбцов. Можно добавить любое количество дочерних элементов управления или других элементов управления макетом, имеющихся в Grid . Например, другой элемент управления Grid можно поместить в определенную комбинацию строк и столбцов, а для этого нового Grid затем можно задать больше строк и столбцов и собственные дочерние элементы.

      Элемент управления определяет строки и столбцы, в которых будут находиться элементы управления. В сетке всегда объявлена одна строка и столбец, то есть сетка по умолчанию является отдельной ячейкой. Это не обеспечивает большую гибкость при размещении элементов управления.

      Прежде чем добавлять новые строки и столбцы, добавьте новый атрибут в элемент : Margin=»10″ . Будет вставлена сетка, благодаря чему окно будет выглядеть немного лучше.

      Затем определите две строки и два столбца, разделив сетку на четыре ячейки:

      Выберите сетку в редакторе кода XAML или в конструкторе XAML. Вы увидите, что в конструкторе XAML отображается каждая строка и столбец:

      A WPF app with the margin set on a grid

      Добавление первого элемента управления

      После создания сетки можно приступать к добавлению в нее элементов управления. Начните с элемента управления Label. Создайте новый элемент внутри элемента после определений строк и столбцов, а затем присвойте ему строковое значение Names :

                

      определяет содержимое Names . Некоторым элементам управления известно, как управлять содержимым, а другим — нет. Содержимое элемента управления сопоставляется со свойством Content . При задании содержимого с помощью синтаксиса атрибутов XAML можно использовать следующий формат:

      У нас есть проблема, поскольку метка занимает половину окна, так как она была автоматически назначена первой строке и столбцу сетки. Для первой строки нам не нужно много пространства, поскольку мы будем использовать эту строку только для метки. Измените атрибут Height первого параметра с * на Auto . Значение Auto автоматически изменяет размер строки сетки под размер ее содержимого (в данном случае это элемент управления Label).

      Обратите внимание, что теперь в конструкторе отображается метка, занимающая небольшую часть доступной высоты. Теперь имеется больше места для следующей строки. Большинство элементов управления определяют значения высоты и ширины, которые они должны занимать. Например, элемент управления Label имеет такое значение высоты, которое позволяет его прочитать.

      A WPF app with the margin set on a grid and a label control in the first row

      Размещение элементов управления

      Давайте поговорим о размещении элементов управления. Метка, созданная в разделе выше, автоматически помещается в строку 0 и столбец 0 сетки. Нумерация строк и столбцов начинается с 0 и увеличивается на 1 для каждой новой строки или столбца. Элементу управления ничего не известно о сетке, и элемент управления не определяет свойства для управления своим размещением в сетке. Элемент управления можно даже поместить в другой элемент управления макета с собственными набором правил, которые определяют способ размещения элементов управления.

      Как указать элементу управления, что ему следует использовать другую строку или столбец, если элемент управления не имеет сведений о сетке? В этом случае на помощь придут вложенные свойства! Сетка использует эффективную систему свойств, предоставляемую WPF. Сетка определяет новые свойства, которые дочерние элементы управления могут объявлять и использовать. Свойства фактически не существуют в самом элементе управления, они вкладываются сеткой при добавлении элемента управления в сетку.

      Сетка определяет два свойства для определения размещения строк и столбцов дочернего элемента управления: Grid.Row и Grid.Column . Если эти свойства опущены в элементе управления, предполагается, что они имеют значения по умолчанию 0, поэтому элемент управления помещается в строку 0 и столбец 0 сетки. Попробуйте изменить расположение элемента управления , присвоив атрибуту Grid.Column значение 1 :

       

      Обратите внимание, что метка теперь переместилась во второй столбец. Вложенные свойства Grid.Row и Grid.Column можно использовать для размещения последующих элементов управления, которые мы создадим. Но на этом этапе следует вернуть метку в строку 0.

      Создание поля со списком имен

      Теперь, когда сетка имеет правильный размер и создана метка, добавьте элемент управления «Список» в строку под меткой. Список будет находиться в строке 1 и столбце 0 . Присвоим этому элементу управления имя lstNames . После присвоения имени элементу управления на него можно ссылаться в коде. Имя присваивается элементу управления с помощью атрибута x:Name .

                

      Добавление оставшихся элементов управления

      Последние два элемента управления, которые предстоит добавить, — это текстовое поле и кнопка, которые пользователь будет использовать для ввода имени, добавляемого в список. Однако вместо того, чтобы пытаться создать больше строк и столбцов для сетки, эти элементы управления будут размещены в элементе управления .

      Панель стека отличается от сетки тем, как в ней размещаются элементы управления. В сетке для указания того, где должны располагаться элементы управления, вы используете свойства Grid.Row и Grid.Column , тогда как в панели стека это выполняется автоматически: сначала размещается первый элемент управления, затем после него следующий элемент управления, и так до тех пор, пока не будут размещены все элементы управления. Элементы управления размещаются в «стек» один под другим.

      Создайте элемент управления после списка и вставьте его в строку 1 и столбец 1 сетки. Добавьте еще один атрибут с именем Margin и значением 5,0,0,0 :

              

      Атрибут Margin ранее уже использовался в сетке, однако теперь мы поместим только одно значение, 10 . Мы использовали значение 5,0,0,0 в панели стека. Поле является типом Thickness и может интерпретировать оба значения. Толщина определяет пространство вокруг каждой стороны прямоугольника, слева, сверху, справа, снизу, соответственно. Если значение поля является одним значением, оно используется для всех четырех сторон.

      Затем создайте и элемент управления в .

          

      Макет окна готов. Однако в наше приложение следует добавить логику, чтобы оно работало. Далее необходимо подключить события элемента управления к коду, чтобы приложение выполняло действия.

      Добавление кода для события Click

      Созданная нами кнопка имеет событие Click , возникающее, когда пользователь нажимает кнопку. Можно подписаться на это событие и добавить код, который будет добавлять имя в список. Как и при задании свойства элемента управления путем добавления атрибута XAML, можно использовать атрибут XAML для подписки на событие. Задайте для атрибута Click значение ButtonAddName_Click .

          

      Теперь необходимо создать код обработчика. Щелкните правой кнопкой мыши ButtonAddName_Click и выберите Перейдите к определению. При этом в коде будет создан метод, соответствующий введенному имени обработчика.

      private void ButtonAddName_Click(object sender, RoutedEventArgs e)
      Private Sub ButtonAddName_Click(sender As Object, e As RoutedEventArgs) End Sub 

      Затем добавьте следующий код для выполнения следующих трех шагов:

      1. Проверка того, что в текстовом поле содержится имя.
      2. Проверка того, что имя, указанное в текстовом поле, еще не добавлено.
      3. Добавление имени в список.
      private void ButtonAddName_Click(object sender, RoutedEventArgs e) < if (!string.IsNullOrWhiteSpace(txtName.Text) && !lstNames.Items.Contains(txtName.Text)) < lstNames.Items.Add(txtName.Text); txtName.Clear(); >> 
      Private Sub ButtonAddName_Click(sender As Object, e As RoutedEventArgs) If Not String.IsNullOrWhiteSpace(txtName.Text) And Not lstNames.Items.Contains(txtName.Text) Then lstNames.Items.Add(txtName.Text) txtName.Clear() End If End Sub 

      Выполнить приложение

      Теперь, когда у нас есть код события, можно запустить приложение, нажав клавишу F5 или выбрав пункт меню Отладка>Начать отладку. Отобразится окно, и вы можете ввести имя в текстовое поле, а затем добавить его, нажав кнопку.

      Running a Windows Presentation Foundation (WPF) for .NET app.

      Следующие шаги

      Совместная работа с нами на GitHub

      Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.

      Добавление поиска в окно инструментов

      Область применения:yesVisual Studio Visual Studio для Mac noVisual Studio Code no

      При создании или обновлении окна инструментов в расширении можно добавить ту же функцию поиска, которая отображается в другом месте Visual Studio. Эта функция включает следующие функции:

      • Поле поиска, которое всегда находится в пользовательской области панели инструментов.
      • Индикатор хода выполнения, наложенный на само поле поиска.
      • Возможность отображать результаты сразу после ввода каждого символа (мгновенного поиска) или только после выбора клавиши ВВОД (поиск по запросу).
      • Список, в котором показаны термины, для которых вы выполнили поиск в последнее время.
      • Возможность фильтрации поиска по определенным полям или аспектам целевых объектов поиска.

      Следуя этому пошаговому руководству, вы узнаете, как выполнять следующие задачи:

      1. Создайте проект VSPackage.
      2. Создайте окно средства, содержащее UserControl с текстовым полем только для чтения.
      3. Добавьте поле поиска в окно инструментов.
      4. Добавьте реализацию поиска.
      5. Включите мгновенный поиск и отображение индикатора выполнения.
      6. Добавьте параметр «Вариант сопоставления».
      7. Добавьте только фильтр только строк поиска.

      Создание проекта VSIX

      1. Создайте проект VSIX с именем TestToolWindowSearch окна инструментов с именем TestSearch. Если вам нужна помощь в этом, см. статью «Создание расширения с помощью окна инструментов».

      Создание окна средства

      1. TestToolWindowSearch В проекте откройте файл TestSearchControl.xaml.
      2. Замените существующий блок следующим блоком, который добавляет доступ только для TextBoxUserControl чтения в окно инструментов.
      using System.Text; 
      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(); >> 
      Partial Public Class MyControl Inherits System.Windows.Controls.UserControl Public Property SearchResultsTextBox As System.Windows.Controls.TextBox Public Property SearchContent As String Public Sub New() ' This call is required by the designer. InitializeComponent() ' Add any initialization after the InitializeComponent() call. Me.SearchResultsTextBox = resultsTextBox Me.SearchContent = buildContent Me.SearchResultsTextBox.Text = Me.SearchContent End Sub Private Function BuildContent() As String Dim sb As New System.Text.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() End Function End Class 

      Добавление поля поиска в окно инструментов

      1. В файле TestSearch.cs добавьте следующий код в TestSearch класс. Код переопределяет SearchEnabled свойство, чтобы метод доступа возвращал true . Чтобы включить поиск, необходимо переопределить SearchEnabled свойство. Класс ToolWindowPane реализует IVsWindowSearch и предоставляет реализацию по умолчанию, которая не включает поиск.
      public override bool SearchEnabled < get < return true; >> 

      Добавление реализации поиска

      При включении поиска по объекту ToolWindowPane,как и в предыдущей процедуре, окно инструментов создает узел поиска. Этот узел настраивает и управляет процессами поиска, которые всегда происходят в фоновом потоке. ToolWindowPane Так как класс управляет созданием узла поиска и настройкой поиска, необходимо создать только задачу поиска и предоставить метод поиска. Процесс поиска происходит в фоновом потоке и вызовы элемента управления окном инструментов происходят в потоке пользовательского интерфейса. Поэтому необходимо использовать метод ThreadHelper.Invoke* для управления вызовами, которые вы выполняете в работе с элементом управления.

        В файле TestSearch.cs добавьте следующие 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; 
      • Переопределяет CreateSearch метод для создания задачи поиска.
      • Переопределяет ClearSearch метод для восстановления состояния текстового поля. Этот метод вызывается, когда пользователь отменяет задачу поиска, а также когда пользователь задает или отменяет параметры или фильтры. ClearSearch Оба CreateSearch и вызываются в потоке пользовательского интерфейса. Поэтому доступ к текстовому поле не требуется с помощью метода ThreadHelper.Invoke* .
      • Создает класс, который TestSearchTask наследует от VsSearchTask, который предоставляет реализацию IVsSearchTaskпо умолчанию. В TestSearchTask конструкторе устанавливается частное поле, которое ссылается на окно инструментов. Чтобы предоставить метод поиска, переопределите OnStartSearch методы и OnStopSearch методы. Метод заключается в OnStartSearch реализации процесса поиска. Этот процесс включает выполнение поиска, отображение результатов поиска в текстовом поле и вызов реализации базового класса этого метода, чтобы сообщить о завершении поиска.
      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; >> 
      1. Перестройте проект и запустите отладку.
      2. В экспериментальном экземпляре Visual Studio снова откройте окно инструментов, введите текст поиска в окне поиска и нажмите клавишу ВВОД. Должны отображаться правильные результаты.

      Настройка поведения поиска

      Изменив параметры поиска, можно внести различные изменения в способе отображения элемента управления поиском и способах выполнения поиска. Например, можно изменить подложку (текст по умолчанию, отображаемый в поле поиска), минимальную и максимальную ширину элемента управления поиска и показать ли индикатор выполнения. Вы также можете изменить точку, в которой результаты поиска начинают отображаться (по запросу или мгновенному поиску) и отображать список терминов, для которых вы недавно искали. Полный список параметров можно найти в SearchSettingsDataSource классе.

        В файле TestSearch.cs* добавьте следующий код в TestSearch класс. Этот код включает мгновенный поиск вместо поиска по запросу (это означает, что пользователю не нужно щелкнуть ВВОД). Код переопределяет ProvideSearchSettings метод в TestSearch классе, который необходим для изменения параметров по умолчанию.

      public override void ProvideSearchSettings(IVsUIDataSource pSearchSettings)
      public override void ProvideSearchSettings(IVsUIDataSource pSearchSettings)

      Чтобы появилась панель выполнения, необходимо сообщить о ходе выполнения. Чтобы сообщить о ходе выполнения, раскомментируйте следующий код в OnStartSearch методе TestSearchTask класса:

      SearchCallback.ReportProgress(this, progress++, (uint)contentArr.GetLength(0)); 
      System.Threading.Thread.Sleep(100); 

      Чтобы пользователи могли уточнить свои поисковые запросы

      Вы можете разрешить пользователям уточнять поисковые запросы с помощью таких параметров, как «Совпадение» или «Совпадение всего слова«. Параметры могут быть логическими, которые отображаются как проверка поля или команды, которые отображаются в виде кнопок. В этом пошаговом руководстве вы создадите логический параметр.

        В файле TestSearch.cs добавьте следующий код в TestSearch класс. Код переопределяет SearchOptionsEnum метод, который позволяет реализации поиска определить, включен или отключен заданный параметр. В коде SearchOptionsEnum добавляется параметр сопоставления регистра IVsEnumWindowSearchOptions перечислителю. Вариант сопоставления регистра также доступен в качестве MatchCaseOption свойства.

      private IVsEnumWindowSearchOptions m_optionsEnum; public override IVsEnumWindowSearchOptions SearchOptionsEnum < get < if (m_optionsEnum == null) < Listlist = new List(); 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; > > 
      matchCase = m_toolWindow.MatchCaseOption.Value; 
      1. Выполните сборку решения и запустите отладку. Откроется экспериментальный экземпляр.
      2. В окне инструментов щелкните стрелку ВНИЗ в правой части текстового поля. Появится поле «Совпадение » проверка.
      3. Выберите поле «Совпадение» проверка поле, а затем выполните некоторые поиски.

      Добавление фильтра поиска

      Можно добавить фильтры поиска, позволяющие пользователям уточнить набор целевых объектов поиска. Например, файлы можно фильтровать в проводник по датам, в которых они были изменены в последнее время, и их расширения имени файла. В этом пошаговом руководстве вы добавите фильтр только для даже строк. Когда пользователь выбирает этот фильтр, узел поиска добавляет строки, указанные в запросе поиска. Затем эти строки можно определить внутри метода поиска и отфильтровать целевые объекты поиска соответствующим образом.

        В файле TestSearch.cs добавьте следующий код в TestSearch класс. Код реализуется SearchFiltersEnum путем добавления, WindowSearchSimpleFilter указывающего фильтрацию результатов поиска таким образом, чтобы отображались только даже строки.

      public override IVsEnumWindowSearchFilters SearchFiltersEnum < get < Listlist = new List(); list.Add(new WindowSearchSimpleFilter("Search even lines only", "Search even lines only", "lines", "even")); return new WindowSearchFilterEnumerator(list) as IVsEnumWindowSearchFilters; > > 
      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; > 
      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(); > 

      Как сделать поиск в wpf

      Сообщений: 15

      Поиск в DataGrid по тексту

      Здравствуйте. Подскажите пожалуйста, как можно реализовать поиск в DataGrid через TextBox? Все мои попытки к сожалению безуспешны. Пример на фото

      using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using MySql.Data.MySqlClient; namespace Diplom < /// /// Логика взаимодействия для student.xaml /// public partial class student : Page < private connect conn; MySqlDataReader dataReader; private DataFiles dataFiles; private Student_list objEmp; public student() < InitializeComponent(); FillCombobox(); >MySqlConnection con = new MySqlConnection(); private void FillCombobox() < GroupCombobox.Items.Clear(); conn = new connect(); conn.OpenConection(); dataReader = conn.DataReader("Select name FROM `group`"); while (dataReader.Read()) < GroupCombobox.Items.Add(dataReader[0].ToString()); >conn.CloseConnection(); > private void GroupCombobox_SelectionChanged(object sender, SelectionChangedEventArgs e) < dataFiles = new DataFiles(); dataGrid.ItemsSource = dataFiles.GetAllStudent(GroupCombobox.SelectedValue.ToString()); Listsource = new List(); conn = new connect(); conn.OpenConection(); dataReader = conn.DataReader("Select name FROM `group`"); while (dataReader.Read()) < source.Add(dataReader[0].ToString()); >conn.CloseConnection(); groupList.ItemsSource = source; > private void Delete(object sender, RoutedEventArgs e) < try < var Res = MessageBox.Show("Уверены что хотите удалить запись?", "Проверка", MessageBoxButton.YesNo); if (Res == MessageBoxResult.Yes) < dataFiles.DeleteStudent(objEmp); >> catch (Exception ex) < MessageBox.Show(ex.Message); >> private void Edit(object sender, RoutedEventArgs e) < try < var Res = MessageBox.Show("Отредактировать данные?", "Подтверждение", MessageBoxButton.YesNo); if (Res == MessageBoxResult.Yes) < dataFiles.UpdateStudent(objEmp); >> catch (Exception ex) < MessageBox.Show(ex.Message); >> private void DataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e) < try < FrameworkElement element_EmpId = dataGrid.Columns[0].GetCellContent(e.Row); if (element_EmpId.GetType() == typeof(TextBox)) < var eno = ((TextBox)element_EmpId).Text; objEmp.id = Convert.ToInt16(eno); >FrameworkElement element_EmpNo = dataGrid.Columns[1].GetCellContent(e.Row); if (element_EmpNo.GetType() == typeof(TextBox)) < var eno = ((TextBox)element_EmpNo).Text; objEmp.FIO = Convert.ToString(eno); >FrameworkElement element_EmpName = dataGrid.Columns[2].GetCellContent(e.Row); if (element_EmpName.GetType() == typeof(ComboBox)) < var ename = ((ComboBox)element_EmpName).SelectedValue.ToString(); objEmp.group = ename; >> catch (Exception ex) < MessageBox.Show(ex.Message); >> private void DataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e) < objEmp = dataGrid.SelectedItem as Student_list; >//текстовое поле для поиска в dataGrid private void tb_TextChanged(object sender, TextChangedEventArgs e) < for (int i = 0; i < dataGrid.Items.Count; i++) < string cellContent = objEmp.FIO.ToString(); try < if (cellContent != null && cellContent.Substring(0, tb.Text.Length).Equals(tb.Text)) < object item = dataGrid.Items[i]; dataGrid.SelectedItem = item; dataGrid.ScrollIntoView(item); break; >> catch < >> > > >

      Изображения

      BaavA.jpg (70.1 Кб, 63 просмотров)
      андрей1107
      Посмотреть профиль
      Найти ещё сообщения от андрей1107

      Поиск в DataGrid WPF

      Есть форма на ней есть DataGrid в DataGrid есть 5 колонок (Фамилия,Имя,Отчестно,Телефон,Электронная почта) надо сделать поиск по 3 сразу колонкам либо по 1 (только для колонок Фамилия,Имя,Отчество) если нашло, то красить фон оранжевым, а шрифт черным. Пример интерфейса:

      Если знаете как сделать такое подскажите пожалуйста уже 2 дня ищу в интернете не могу найти что-то полезное.

      Отслеживать
      задан 4 июл 2019 в 12:41
      3 3 3 бронзовых знака

      1 ответ 1

      Сортировка: Сброс на вариант по умолчанию

      Готовый ответ дать — не так интересно, (не факт, но) может быть, не так полезно, дольше и сложнее. В комментариях писать — не поместится. Пишу тут. Но не полный ответ, а наметки.

      Странно, что за два дня не нашлось ничего полезного в интернете.

      Пишу не ради базы знаний. Советы не выверенные, а то, что сходу пришло на ум. Простите, тут немного сумбурно, не ставил целью хорошее оформление и четкое полное описание. Просто, какие-то соображения.

      public class Person < public string Client_id < get; set; >//int. public string Fam < get; set; >public string Name < get; set; >public string Otch < get; set; >public string Phone < get; set; >public string E_mail < get; set; >> 
      • Правильнее делать через CollectionViewSource, но, кажется, в данном случае, можно и попроще
      • Можно было бы использовать delayed binding text box (например, вот какой-то), но буду говорить о варианте попроще
      public partial class ViewModel: INotifyPropertyChanged < private /*например, лист*/ List_DefaultPersons; private /*например, лист*/ List _Persons; public /*например, лист*/ List Persons < get < return _Persons; >set < _Persons = value; RaisePropertyChanged(nameof(Persons)); >> private string _SearchWord; public string SearchWord < get < return _SearchWord; >set < _SearchWord = value; Persons = FilterPersons(_DefaultPersons); >> //. > 
      • Про интерфейс INotifyPropertyChanged можно найти в интернете, здесь его не реализовывал, а использовал partial , якобы есть другой файл в котором реализация INotifyPropertyChanged . Суть в том, что при изменении свойства вызываем событие о его изменении.
      • где-нибудь в конструкторе класса можно инициализировать коллекцию персон
      • еще в конструкторе можно присвоить Persons = _DefaultPersons
      • в методе FilterPrsons надо будет написать логику фильтрации списка и поместить этот метод во ViewModel . Для начала можно просто сделать какую-нибудь промежуточную проверку, чтобы от общего потом к частному:
      private List FilterPrsons() < var result = _DefaultPersons .Where(prsn =>prsn.Name.Contains(SearchWord)) .ToList(); return result; > 
      • кстати, SearchWord логичнее назвать SearchPhrase
      • Приведенная выше ViewModel — класс, который в потенциале может стать контекстом данных для того xaml -а, который приведен в вопросе. Чтобы он им стал, надо DataContext -у MainWindow присвоить экземпляр этого класса.
      • Можно добавить в SearchBox UpdateSourceTrigger=PropertyChanged , например, так:
      " Width="50" /> 
      • но лучше добавить кнопку / или по клавише Enter, например: так или так или еще как-то. Иначе, если фильтрация долгая (таблица большая), то при каждом введении символа будет тормозить. Можно убрать UpdateSourceTrigger=PropertyChanged и без кнопок, без Enter-а, но тогда надо будет после введения фразы кликать в сторону, чтобы был задействован связующий binding.
      • суть с командами для кнопки (если кнопка будет) такая, чтобы во ViewModel -е было такое свойство, которое являлось бы реализацией ICommand , а потом в xaml-е присвоить его свойству кнопки Command эту штуку
      • в xaml-е, в таблице DataGrid надо прописать такую штуку:
      • а, да, там же еще есть ComboBox .. Можно его тоже привязать к свойствам ViewModel-и, например, (чтобы проще было) иметь там 4 свойства типа bool . Потом учитывать эти свойства в методе FilterPrsons . Только не забыть про такую методологию:
       private bool _x; public bool x < get < return _x; >set < _x = value; RaisePropertyChanged(nameof(X)); >> 

      Если делать без ViewModel, прямо в MainWindow.xaml.cs , то:

      • Можно напрямую там присваивать:
      dataGrid.ItemsSource = Persons; 
      • Коллекцию персон можно определить прямо в MainWindow.xaml.cs , как и всё остальное на c#
       private /*например, лист*/ List _DefaultPersons; private /*например, лист*/ List _Persons; 
      • тогда на TextBox x:Name=»SearchBox» надо будет повесить событие, например так:
      private void textChangedEventHandler(object sender, TextChangedEventArgs args) < //здесь можно собрать данные из: //SearchBox //ComboBox (там нет названия, можно присвоить) //далее отфильтровать персон методом FilterPersons() //далее dataGrid.ItemsSource = _Persons; >
      • без ViewModel намного проще сделать обработчик для кнопки. Так же как и , только там Button и событие Click , далее если щелкнуть правой или левой кнопке по введенному имени (прямо в редакторе xaml-а) обработчика, то можно перейти к коду / либо посмотреть в интернете про событие Click и дописать в MainWindow.xaml.cs .

      Фильтрация данных в элементе ListView

      Мы уже совершали несколько различных задач вместе с ListView, как группировка и сортировка, но существует и другая очень важная возможность — фильтрация. Очевидно, что Вы могли бы ограничить количество элементов, которое могли бы добавить в первую очередь, но часто Вам нужно фильтровать ListView динамично, во время выполнения, обычно, основываясь на пользовательской строки фильтрации. К счастью для нас, механизмы view элемента ListView также позволяют с лёгкостью это выполнить, как мы наблюдали в случае сортировки и группировки.

      Фильтрацию довольно просто выполнить, так что давайте перейдём прямиком к примеру и позже его обсудим:

      using System; using System.Collections.Generic; using System.Windows; using System.Windows.Data; namespace WpfTutorialSamples.ListView_control < public partial class FilteringSample : Window < public FilteringSample() < InitializeComponent(); Listitems = new List(); items.Add(new User() < Name = "John Doe", Age = 42 >); items.Add(new User() < Name = "Jane Doe", Age = 39 >); items.Add(new User() < Name = "Sammy Doe", Age = 13 >); items.Add(new User() < Name = "Donna Doe", Age = 13 >); lvUsers.ItemsSource = items; CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(lvUsers.ItemsSource); view.Filter = UserFilter; > private bool UserFilter(object item) < if(String.IsNullOrEmpty(txtFilter.Text)) return true; else return ((item as User).Name.IndexOf(txtFilter.Text, StringComparison.OrdinalIgnoreCase) >= 0); > private void txtFilter_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e) < CollectionViewSource.GetDefaultView(lvUsers.ItemsSource).Refresh(); >> public enum SexType < Male, Female >; public class User < public string Name < get; set; >public int Age < get; set; >public string Mail < get; set; >public SexType Sex < get; set; >> >

      Часть с XAML довольна проста: мы имеем TextBox, где пользователь может ввести значение поиска, и ListView для отображения результата.

      В программной части мы начинаем с добавления нескольких User объектов в ListView так же, как мы делали в предыдущих примерах. Интересующая нас часть начинается в последних двух строках конструктора, где вы приобретаем ссылку на экземпляр CollectionView для ListView и далее назначаем делегат свойству Filter. Этот делегат указывает на функцию, названную UserFilter, которую мы реализовали ниже. Она обрабатывает каждый элемент, указанный в первом(и только) параметре и возвращает результат в виде логического значения, указывающего на то, должен ли данный элемент быть виден в списке.

      В методе UserFilter() мы смотрим на элемент TextBox(txtFilter), чтобы увидеть содержит ли он любой текст — и если содержит, мы используем его для проверки содержания имени User(что является свойством, которое мы решили фильтровать) в введённой строке и возвращаем положительный или отрицательный результат в зависимости от его значения. Если TextBox пуст, то возвращаем true, так как в этом случае мы хотим, чтобы все элементы были видимы.

      Событие txtFilter_TextChanged также важно. При каждом изменении текста мы получаем ссылку на объект View элемента ListView и далее на нём вызываем метод Refresh(). Это гарантирует точное срабатывание делегата Filter при каждом изменении значения строки поиска/фильтра в поле ввода пользователем.

      Заключение

      Это была довольно простая реализация, но с того момента, как Вы получите доступ ко всем элементам(в этом случае это класс User) вы сможете выполнять любые типы фильтрации какие захотите, так как Вы имеете полный доступ ко всей информации о каждом элементе в списке. Например, образец выше может быть легко изменён для фильтрации по возрасту, учитывающего свойство Age вместо свойства Name, или же Вы могли бы изменить его таким образом, чтобы учитывалось более одного свойства, например, для фильтрации пользователей в возрастом ниже X И с именем, которое не содержит «Y».

      This article has been fully translated into the following languages:

      Is your preferred language not on the list? Click here to help us translate this article into your language!

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *