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

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

  • автор:

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

Элемент CheckBox представляет собой обычный флажок. Данный элемент является производным от класса ToggleButton и поэтому может принимать также три состояния: Checked , Unchecked и Intermediate .

Чтобы получить или установить определенное состояние, надо использовать свойство IsChecked, которое также унаследовано от ToggleButton:

   " Height="20" Content="Неопределено"/> 

Установка свойства IsChecked=»» задает неопределенное состояние для элемента checkbox. Остальные два состояния задаются с помощью True и False. В данном примере также привязан к двум флажкам обработчик события Checked . Это событие возникает при установке checkbox в отмеченное состояние.

А атрибут IsThreeState=»True» указывает, что флажок может находиться в трех состояниях.

Элемент checkbox в WPF

Ключевыми событиями флажка являются события Checked (генерируется при установке флажка в отмеченное состояние), Unchecked (генерируется при снятии отметки с флажка) и Indeterminate (флажок переведен в неопределенное состояние). Например, определим флажок:

А в файле кода C# пропишем для него обработчики:

private void checkBox_Checked(object sender, RoutedEventArgs e) < MessageBox.Show(checkBox.Content.ToString() + " отмечен"); >private void checkBox_Unchecked(object sender, RoutedEventArgs e) < MessageBox.Show(checkBox.Content.ToString() + " не отмечен"); >private void checkBox_Indeterminate(object sender, RoutedEventArgs e)

Программное добавление флажка:

using System.Windows; using System.Windows.Controls; namespace ControlsApp < public partial class MainWindow : Window < public MainWindow() < InitializeComponent(); // создаем флажок CheckBox checkBox2 = new CheckBox < Content = "Новый флажок", MinHeight = 20, IsChecked=true >; // установка обработчика checkBox2.Checked += checkBox_Checked; // добавление в StackPanel stackPanel.Children.Add(checkBox2); > private void checkBox_Checked(object sender, RoutedEventArgs e) < CheckBox chBox = (CheckBox)sender; MessageBox.Show(chBox.Content.ToString() + " отмечен"); >> >

RadioButton

Элемент управления, также производный от ToggleButton, представляющий переключатель. Главная его особенность — поддержка групп. Несколько элементов RadioButton можно объединить в группы, и в один момент времени мы можем выбрать из этой группы только один переключатель. Например,

Элемент RadioButton в WPF

Чтобы включить элемент в определенную группу, используется свойство GroupName . В данном случае у нас две группы — Languages и Technologies. Мы можем отметить не более одного элемента RadioButton в пределах одной группы, зафиксировав тем самым выбор из нескольких возможностей.

Чтобы проследить за выбором того или иного элемента, мы также можем определить у элементов событие Checked и его обрабатывать в коде:

Обработчик в файле кода:

private void RadioButton_Checked(object sender, RoutedEventArgs e)

Программное добавление элемента RadioButton:

using System.Windows; using System.Windows.Controls; namespace ControlsApp < public partial class MainWindow : Window < public MainWindow() < InitializeComponent(); RadioButton rb = new RadioButton < IsChecked = true, GroupName = "Languages", Content = "JavaScript" >; rb.Checked += RadioButton_Checked; stackPanel.Children.Add(rb); > private void RadioButton_Checked(object sender, RoutedEventArgs e) < RadioButton pressed = (RadioButton)sender; MessageBox.Show(pressed.Content.ToString()); >> >

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

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

Возьмем простейший элемент-список — ListBox и определим в файле MainWindow.xaml следующий интерфейс:

  Tom Bob Sam Alice   

Элемент ItemsControl и списки в WPF и C#

Все элементы, размещенные внутри спискового элемента ListBox, представляют элементы списка.

Управление списком

Коллекция объектов внутри элемента-списка доступна в виде свойства Items . Для управления элементами из этой коллекции мы можем использовать следующие методы:

  • Add(object item) : добавление элемента
  • Clear() : полная очистка коллекции
  • Insert(int index, object item) : вставка элемента по определенному индексу в коллекции
  • Remove(object item) : удаление элемента
  • RemoveAt(int index) : удаление элемента по индексу

А свойство Count позволяет узнать, сколько элементов в коллекции.

Например, оставим предыдущий интерфейс и в файле связанного кода MainWindow.xaml.cs добавим и удалим программно несколько элементов:

using System.Windows; namespace MetanitApp < public partial class MainWindow : Window < public MainWindow() < InitializeComponent(); usersList.Items.Remove("Sam"); // удаляем элемент "Sam" usersList.Items.RemoveAt(1); // удаляем второй элемент usersList.Items.Add("Kate"); // Добавляем элемент "Kate" usersList.Items.Insert(0, "Mike"); // Вставляем элемент "Mike" на первое место в списке >> >

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

Методы управления списком в ListBox в WPF и C#

При вызове методов, которые используют индексы, как выше методы RemoveAt(index) и Insert(index, object) , следует учитывать, что передаваемые индексы должны быть действительны. Естественно мы не можем удалить, к примеру, второй объект, если списке только один объект или вообще нет объектов. В этом случае мы можем проверять длину списка:

if(usersList.Items.Count > 1) // если в списке больше 1 элемента < usersList.Items.Insert(1, "Mike"); // Вставляем элемент "Mike" на второе место usersList.Items.RemoveAt(2); // удаляем третий элемент >

Отображение сложных данных

Списковые элементы могут отображать не только простые строки или числа, но и сложные данные. Например, создадим в коде новый класс Person:

public class Person < public string Name < get; set; >= ""; public int Age < get; set; >public override string ToString() < return $"Name: Age: "; > >

Теперь создадим в xaml набор объектов этого класса Person и выведем в их в списке:

Поскольку мы используем класс, определенный в текущем проекте, то соответственно у нас обязательно должно быть подключено пространство имен проекте. В моем случае проект (и пространство имен) называется «MetanitApp». Соответственно у меня это пространство имен проецируется на префикс local :

xmlns:local="clr-namespace:MetanitApp"

В принципе по умолчанию WPF уже его подключает. После этого через префикс «local» можно обращаться к классу Person: «local:Person».

Кроме того, чтобы не возникало проблем с разметкой XAML, желательно сделать перестроение проекта. И в итоге ListBox выведет все объекты:

Вывод списка объектов в ListBox в WPF и C#

По умолчанию списковые элементы выводят то, что возвращает метод ToString() объекта. Именно для этой демонстрации и реализован данный метод в классе Person выше. Но также с помощью свойства DisplayMemberPath можно установить свойство объекта, значение которого будет отображаться в списке. Например, отобразим только имя:

Свойство DisplayMemberPath в ListBox в WPF и C#

В этом случае в коде C# таким же образом можно добавлять и удалять данные:

var firstPerson = usersList.Items[0]; // получаем первый объект usersList.Items.Remove(firstPerson); // удаляем его usersList.Items.Add(new Person < Name = "Kate", Age = 23 >); // добавляем новый объект

ItemsSource

Нам необязательно вручную заполнять значения элемента управления списком, так как мы можем установить свойство ItemsSource , задав в качестве параметра коллекцию, из которой будет формироваться элемент управления списком. Например, в коде xaml-разметки определим пустой список:

А в файле отделенного кода выполним наполнение списка:

using System.Windows; using System.Collections.Generic; namespace MetanitApp; public partial class MainWindow : Window < public MainWindow() < InitializeComponent(); usersList.ItemsSource = new List() < new Person, new Person , new Person >; // устанавливаем отображаемое свойство usersList.DisplayMemberPath = "Name"; > >

Но стоит учитывать, что если мы наполняем элемент управления списком через свойство ItemsSource , то мы не сможем использовать выше рассмотренные методы Add/Remove/RemoveAt/Insert/Clear для добавления/удаления элементов списка. В этом случае для управления элементами непосредственно к самому источнику данных. Например, определим в коде xaml кнопку для добавления одного объекта:

По нажатию на кнопку будет вызываться метод Button_Click . И в файле связанного кода C# определим данный метод и наполним ListBox данными:

using System.Windows; using System.Collections.Generic; namespace MetanitApp; public partial class MainWindow : Window < Listpeople = new List() < new Person, new Person , new Person >; public MainWindow() < InitializeComponent(); usersList.ItemsSource = people; >private void Button_Click(object sender, RoutedEventArgs e) < people.Add(new Person < Name = "Mike", Age = 29 >); usersList.Items.Refresh(); > >

Здесь в качестве источника данных выступает список people, и из этого списка ListBox будет брать данные.

В обработчике нажатия кнопки добавляем в список people один объект Person для теста. Обратите внимание, что добавляем именно в стандартный список List , а не в ListBox. ListBox в данном случае просто отображает данные. Но чтобы ListBox обновил свое визуальное представление, после изменения списка people обновляем данные в ListBox:

usersList.Items.Refresh();

Обновление данных в ListBox в WPF и C#

Стоит отметить, что если в качестве источника данных выступает ObservableCollection , то нам не надо вызывает отобновление данных списка, так как коллекция ObservableCollection сама извещает систему об изменениях.

Выбор элементов

Все элементы управления списками поддерживают выделение входящих элементов. Выделенный элемент(ы) можно получить с помощью свойств SelectedItem (SelectedItems), а получить индекс выделенного элемента — с помощью свойства SelectedIndex . Свойство SelectedValue позволяет получить значение выделенного элемента.

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

А в файле кода определим обработчик для этого события:

using System.Windows; using System.Windows.Controls; namespace MetanitApp; public partial class MainWindow : Window < public MainWindow() < InitializeComponent(); >private void usersList_SelectionChanged(object sender, SelectionChangedEventArgs e) < if (usersList.SelectedItem is Person person) < MessageBox.Show(person.Name); >> >

Важно учитывать, что так как в разметке xaml в списке определены элементы Person, то в коде мы можем привести объект usersList.SelectedItem к типу Person.

Подсветка найденных элементов в ListBox’е WPF

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

Разрабатывая один из проектов на .Net, столкнулся со следующей задачей — необходимо было в WPF реализовать поиск элементов (элемент представлял из себя строку) в списке ListBox с подсветкой введенного текста для поиска. После продолжительного поиска в гугле, готовых вариантов решения найдено не было, принялся за реализацию данной задачи.
Минимальные знания, которые потребуются: WPF, C#, LINQ.

Создание интерфейса

Первым делом — составим интерфейс будущего контролла, в данном случае — это будет TextBox, прямо под которым находится ListBox. Элементом ListBox’а будет являться CheckBox, в теле которого находится два TextBlock’а. Хотя их там будет даже 3, но об этом позже. CheckBox — потому что требуется выбрать несколько элементов, при этом выбранные элементы будем поднимать вверх списка (чтобы проще было их найти в огромном списке). Почему 2 TextBlock’a: т.к. стоит задача подсветить найденный кусочек текста во всей фразе, то нам придется разбивать один из TextBlock на Inlines — составные части, у одной из которых надо будет подсветить Background. Второй же TextBlock будет отображать полностью фразу, и будет находиться поверх первого TextBlock’a.

Для примера, в качестве элементов списка, возьмем системные шрифты — получается как раз достаточно большой список объектов (у меня — 257, но тестировал и на большем количестве). Чтобы увидеть, как шрифт применяется, дополним тело CheckBox’а ещё одним TextBlock’ом, в котором разместим фразу «ABCD АБВГ 1234» и будем применять к ней шрифт.

Код шаблона ListBoxItem

                 

Как видно в коде, TextBlock с именем textBackground разбит на 2 части, на два Inlines: textBefore — текст, который будет перед выделением, и textSelect — текст, который будет выделен. Полностью текст шрифта выводится в TextBlock с именем textContent. К TextBlock’у c именем textInFont применяется начертание шрифта, чтобы можно было увидеть, как шрифт отобразится на русских и английских символах, а так же на цифрах.

ListBox будет описывается следующим образом

      " Grid.Row="1" HorizontalContentAlignment="Stretch" ItemTemplate="" SelectionChanged="listBox_SelectionChanged"/> 

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

Программная составляющая

Во первых, необходим класс, который будет содержать все необходимые элементы для привязки данных. Для примера, назовем его Cust

 public class Cust < /// /// название шрифта /// public string Namefont < get; set; >/// /// начертание шрифта /// public FontFamily Fontstyle < get; set; >/// /// выбран шрифт или нет /// public bool isCheck < get; set; >/// /// текст перед выделением /// public String TextBefore < get; set; >/// /// выделенный текст /// public String TextSelect < get; set; >/// /// подсветка выбранного элемента /// public Brush colorGround < get < if (isCheck) return Brushes.LightSkyBlue; else return Brushes.White; >> public Cust(String newFonts, bool check) < Namefont = newFonts; Fontstyle = new FontFamily(Namefont); isCheck = check; >> 

Теперь необходимо создать две коллекции — в первой будем хранить полный список объектов, во втором — только отфильтрованные элементы. И сразу же напишем функцию инициализации контролла

 /// /// Коллекция всех элементов /// private List _collectionSource = new ObservableCollection(); /// /// коллекция фильтрованных элементов /// public List Collection = new ObservableCollection(); public void Init() < //достаем системные шрифты, список сразу делаем сортированным по названию ListfontsList = (Fonts.SystemFontFamilies.OrderBy(f => f.Source).Select(f => f.Source)).ToList(); _collectionSource.Clear(); Collection.Clear(); textCol.Text = fontsList.Count.ToString(); for (int i = 0; i < fontsList.Count; i++) < _collectionSource.Add(new Cust(fontsList[i], false)); Collection.Add(_collectionSource[i]); >listBox.DataContext = Collection; > 

image

Теперь мы можем наблюдать вот такой контролл:

Теперь самое интересное — фильтрация и подсветка. Для фильтрации напишем следующую функцию:

 /// /// фильтрация коллекции /// /// private void FilterItems(string s) < if (string.IsNullOrEmpty(textBoxSearch.Text)) < Collection = new List(_collectionSource.OrderBy(i => !i.isCheck)); foreach (Cust item in Collection) < item.TextSelect = String.Empty; >> else < Collection = new List(_collectionSource.OrderBy(i => !i.Namefont.ToLower().StartsWith(s)). Where(item => item.Namefont.ToLower().Contains(s))); foreach (Cust item in Collection) < item.TextBefore = item.Namefont.Substring(0, item.Namefont.ToLower().IndexOf(s)); item.TextSelect = item.Namefont.Substring(item.Namefont.ToLower().IndexOf(s), s.Length); >> listBox.DataContext = Collection; > 

В случае, если в TextBox’e не было ничего введено, то выбранные элементы автоматически поднимаются в вверх, если же пользователь начал вводить, то после каждого изменения текста в TextBox вызывается функция FilterItems, в которую передается текущей текст в TextBox’е, после чего происходит фильтрация по заданному условию основной коллекции, результат записывается во вторую коллекцию, с которой уже и связывается DataContext ListBox’a. Так же, во второй коллекции для каждого элемента задается TextBefore и TextSelect, к которым как раз привязаны соответствующие по названиям TextBlock’и в шаблоне ListBoxItem.
Сортировка второй коллекции производится сначала по первому вхождению найденного текста, и только потом — вхождение этого текста в остальной части фразы.
При выборе шрифта, либо отмене выбора — происходит событие либо checkControl_Checked, либо checkControl_Unchecked соответственно.

 private void checkControl_Checked(object sender, RoutedEventArgs e) < FilterItems(textBoxSearch.Text.ToLower()); textCol.Text = _collectionSource.Count(i =>i.isCheck).ToString(); > private void checkControl_Unchecked(object sender, RoutedEventArgs e) < FilterItems(textBoxSearch.Text.ToLower()); textCol.Text = _collectionSource.Count(i =>i.isCheck).ToString(); > 

Для случая, если понадобится выбрать все элементы — реализовал возможность выделения всех элементов

 private void checkAll_Checked(object sender, RoutedEventArgs e) < foreach (Cust t in _collectionSource) < t.isCheck = true; >FilterItems(textBoxSearch.Text.ToLower()); textCol.Text = _collectionSource.Count.ToString(); > private void checkAll_Unchecked(object sender, RoutedEventArgs e) < foreach (Cust t in _collectionSource) < t.isCheck = false; >FilterItems(textBoxSearch.Text.ToLower()); textCol.Text = "0"; > 
Итого

image

В итоге — получился вот такой контролл, в котором быстро можно найти один или несколько элементов. При этом — подсвечивается найденный текст в элементе.

Спасибо за внимание. Надеюсь, статья была полезна и интересна.
P.S. исходники можно взять тут narod.ru либо dropbox

CheckBox

Для представления параметров, которые пользователь может выбрать или очистить, в интерфейсе приложения можно использовать CheckBox. Можно устанавливать один флажок или сгруппировать два или более флажков.

На следующем рисунке показаны различные состояния объекта CheckBox.

CheckBox states

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

Ссылка

Связанные разделы

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

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

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

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