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

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

  • автор:

Практическое руководство. Создание ListViewItems с CheckBox

В этом примере показано, как можно отобразить столбец элементов управления CheckBox в элементе управления ListView, в котором используется GridView.

Пример

Чтобы создать столбец с элементами управленияCheckBox в объекте ListView, создайте столбец DataTemplate, содержащий объект CheckBox. Затем присвойте объекту CellTemplate из GridViewColumn в качестве значения DataTemplate.

В следующем примере показан объект DataTemplate, в котором содержится CheckBox. В этом примере свойство IsChecked из объекта CheckBox привязывается к значению свойства IsSelected из объекта ListViewItem, в котором оно содержится. Таким образом, когда выбирается объект ListViewItem, в котором содержится CheckBox, выбирается и сам объект CheckBox.

В следующем примере показано, как можно создать столбец элементов управления CheckBox. Чтобы сделать столбец, в примере для свойства CellTemplate из объекта GridViewColumn задается в качестве значения DataTemplate.

" Width="30"/> 

См. также

  • Control
  • ListView
  • GridView
  • Общие сведения об элементе управления ListView
  • Практические руководства
  • Общие сведения о GridView

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

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

CheckBox

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

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

CheckBox states

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

Ссылка

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

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

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

WPF Как проверить выбранный CheckBox?

Я пытался заново перебрать всю таблицу, чтобы определить номер строки (id), на которой CheckBox стал активным. Также поставил фильтр(первая конструкция if) на те CheckBox’ы, которые уже выведены из БД, то есть true и являются неактивными, так как у пользователя нет возможности изменять уже включенные CheckBox’ы.

private void checkBox(object sender, RoutedEventArgs e) < DataTable req_out = specWindow.Select("SELECT * FROM [dbo].[Request]"); for (int j = 0; j < req_out.Rows.Count; j++) < // перебираем данные active_table = ("" + req_out.Rows[j][4]); if(active_table=="0") < if (statusReq) < MessageBox.Show("Отмечен столбец № " + j); >> > 

Реализация класса коллекции

 public class monitorReq < public string numReq < get; set; >public string fioUser < get; set; >public string department < get; set; >public string cabinet < get; set; >public string numPc < get; set; >public string shortDesc < get; set; >public string longDesc < get; set; >public bool statusReq < get; set; >public bool enableCheck < get; set; >public monitorReq(string _numReq, string _fioUser, string _department, string _cabinet, string _numPc, string _shortDesc, string _longDesc, bool _statusReq, bool _enableCheck) < this.numReq = _numReq; this.fioUser = _fioUser; this.department = _department; this.cabinet = _cabinet; this.numPc = _numPc; this.shortDesc = _shortDesc; this.longDesc = _longDesc; this.statusReq = _statusReq; this.enableCheck = _enableCheck; >> 

введите сюда описание изображения

Подскажите пожалуйста, как определить строку(по сути id), в которой пользователь только что отметил checkbox, чтобы можно было записать это в переменную и отправить в БД? Вот скрин таблицы

Отслеживать
AnatolyWPF
задан 12 мая 2020 в 18:11
AnatolyWPF AnatolyWPF
13 3 3 бронзовых знака
А зачем искать перебором? Разве сам sender не нужный вам checkbox?
12 мая 2020 в 18:34

Вообще да, sender — это и есть тот самый чекбокс. Можно по визуальному дереву найти строку и данные в ней. Но лучше воспользоваться ответом, который я дал ниже. 🙂

12 мая 2020 в 19:26

Попробуйте изменить политику именования переменных: свойства с большой буквы, поля с маленькой и с подчеркиванием, локальные переменные просто с маленькой.

12 мая 2020 в 22:50

@aepot вы читаете мои мысли) Увидел у вас, что переменные начинаются с большой буквы, да и сам VS выдает сообщения, что неправильное наименование. Буду исправляться!

12 мая 2020 в 22:56

@AnatolyWPF и можно без конструктора обойтись, свойства позволяют ограничить доступ, например только < get; >возволяет изменить свойство только при создании класса, < get; private set; >позволяет дополнительно менять свойство внутри класса, ну и < get; set; >— полный доступ. Ну можно еще то же самое наоборот, с ограничением записи. Как создать клас со свойствами и без конструктора, я показал в ответе.

12 мая 2020 в 23:01

1 ответ 1

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

Вы боретесь с контролами, и при этом не используете встроенные возможности WPF. Обратите внимание на шаблон программирования MVVM.

Я покажу короткий пример на базе этого шаблона.

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

public class NotifyPropertyChanged : INotifyPropertyChanged < public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = null) =>PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); > 

Затем потребуется класс с данными, и сразу сделаю его так, чтобы он уведомлял интерфейс об изменениях. Другими словами, если вы внесете изменения в DataGrid , они сразу поменяются в данных, и наоборот. Вам не придется больше взаимодействовать с DataGrid , а только с данными.

public class UserItem : NotifyPropertyChanged < private int _numReq; private string _shortDesc; private string _longDesc; private string _fioUser; private bool _statusReq; public int NumReq < get =>_numReq; set < _numReq = value; OnPropertyChanged(); // уведомляет UI об изменении >> public string ShortDesc < get =>_shortDesc; set < _shortDesc = value; OnPropertyChanged(); >> public string LongDesc < get =>_longDesc; set < _longDesc = value; OnPropertyChanged(); >> public string FioUser < get =>_fioUser; set < _fioUser = value; OnPropertyChanged(); >> public bool StatusReq < get =>_statusReq; set < // сюда попадаем как только изменен чекбокс // при этом не важно, програмно или из UI // можно прямо отсюда кинуть запрос в БД, все нужные данные в прямой видимости _statusReq = value; OnPropertyChanged(); >> > 

Затем, основной класс для MainWindow , который будет содержать все свойства, к которыйм в свою очередь будут привязаны зависимые свойства контролов интерфейса в помощью Binding .

public class MainViewModel : NotifyPropertyChanged < private ObservableCollection_userList; public ObservableCollection UserList // коллекция, к которой привязана DataGrid < get =>_userList; set < _userList = value; OnPropertyChanged(); >> public MainViewModel() < UserList = new ObservableCollection(); > > 

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

public MainWindow()

Чтобы работали подсказки к биндингам в разметке, в параметрах Window в XAML можно указать d:DataContext=»» .

Ну и сама разметка таблицы

        "/>     

Работать с ObservableCollection можно точно так же как с уже знакомым вам List . Она отличается от List в основном тем, что внутри нее вызывается событие CollectionChanged при добавлении или удалнии элементов коллекции, а на него автоматически подписывается DataGrid .

UserList.Add(new UserItem() < NumReq = 1, FioUser = "Семён Семёнович", ShortDesc = "Монитор", LongDesc = "Выключился", StatusReq = false >); 

Про загрузку данных, просто грузите их не в DataGrid , а в коллекцию.

Если решитесь попробовать MVVM, есть еще команды, к ним можно биндить кнопки, меню и прочие контролы, в которых не меняются зависимые свойства, а просто надо что-то сделать, когда что-то нажато. Я не буду добавлять примеры использования команд в этот ответ, но их можно найти в других моих ответах StackOverflow, у меня в профиле.

private ObservableCollection _monitorReqList = new ObservableCollection(); public ObservableCollection MonitorReqList // я бы так назвал < get =>_monitorReqList; set < _monitorReqList = value; OnPropertyChanged(); >> 
public class MonitorReq : NotifyPropertyChanged < // реализация класса данных >

Подсветка найденных элементов в 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

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

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