Я не думаю, что вы сможете сделать это с помощью компаратора «LIKE», поскольку значения, которые вы ищете, являются «числовыми».Чтобы получить фильтр, который вы ищете, вам понадобится фильтр с «> =» и «<=», чтобы увидеть, находится ли целевой возраст в диапазоне.Непонятно, как данные получены изначально, если «возрастной диапазон» в каждой строке представляет собой строку, как показано, то я предлагаю несколько разных хакерских способов.Кроме того, неясно, какие другие столбцы будут в сетке. </p>
Один «хакерский» подход заключается в создании метода, который возвращает новый DataTable
только с теми строками, которые попадают в заданную цель.спектр.Чтобы помочь в этом деле, второй метод, который принимает int
(целевое значение, которое мы ищем), и DataRowView
(AgeRange
, с которым мы сравниваем «целевое» значение).Этот «AgeRange» будет в первом столбце строк.Здесь мы просто берем этот строковый диапазон («0-18») и целевое значение («18»), чтобы увидеть, находится ли это целевое значение в диапазоне, затем возвращаем true или false в зависимости от результата.Это можно сделать с помощью метода string.split
, чтобы разделить строку «AgeRange», и int.TryParse
, чтобы преобразовать строки в числа.Ниже приведен пример этого.
private bool TargetIsInRange(int target, DataRowView row) {
if (row.Row.ItemArray[0] != null) {
string cellValue = row.Row.ItemArray[0].ToString();
string[] splitArray = cellValue.Split('-');
int startValue;
int endValue;
if (!int.TryParse(splitArray[0], out startValue)) {
return false;
}
if (!int.TryParse(splitArray[1], out endValue)) {
return false;
}
if (target >= startValue && target <= endValue)
return true;
}
return false;
}
Приведенный выше метод должен пригодиться при циклическом просмотре строк сетки, чтобы выяснить, какие строки входят в новый фильтр DataTable
.Далее, метод, который делает это циклически по сетке и возвращает отфильтрованный DataTable
.Для каждой строки в сетке мы могли бы вызвать вышеупомянутый метод и добавить строки, которые возвращают true
.
private DataTable GetFilterTable() {
DataTable filterTable = ((DataTable)dgv1.DataSource).Clone();
dgv1.DataSource = gridTable;
int targetValue = -1;
if (int.TryParse(textBox1.Text, out targetValue)) {
foreach (DataGridViewRow row in dgv1.Rows) {
DataRowView dataRow = (DataRowView)row.DataBoundItem;
if (dataRow != null) {
if (TargetIsInRange(targetValue, dataRow)) {
filterTable.Rows.Add(dataRow.Row.ItemArray[0]);
}
}
}
}
return filterTable;
}
Непонятно, где вы вызываете этот фильтр, если вы фильтруете «строки», то, когда пользователь вводит строку фильтра в текстовое поле, сетка будет фильтроваться с каждым символом, нажимаемым пользователем.Это хорошо для строк, однако, в этом случае, используя «цифры», я думаю, кнопка будет более подходящей.Я думаю, это то, что вам придется решить.Объединение всего этого с помощью события Button
click для сигнализации о том, что для фильтрации сетки может выглядеть примерно так:
private DataTable gridTable;
public Form1() {
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) {
gridTable = GetTable();
FillTable(gridTable);
dgv1.DataSource = gridTable;
textBox1.Text = "18";
}
private void FillTable(DataTable dt) {
dt.Rows.Add("0-18");
dt.Rows.Add("19-100");
dt.Rows.Add("0-100");
dt.Rows.Add("17-80");
dt.Rows.Add("18-80");
}
private DataTable GetTable() {
DataTable dt = new DataTable();
dt.Columns.Add("AgeRange", typeof(string));
return dt;
}
private void button1_Click(object sender, EventArgs e) {
if (textBox1.Text == "") {
dgv1.DataSource = gridTable;
return;
}
dgv1.DataSource = GetFilterTable();
}
Подход Hacky 2
Первый подходработает;Тем не менее, я предполагаю, что если будет много данных и много фильтрации, это может стать проблемой производительности.Поэтому в этом подходе вначале предпринимаются дополнительные шаги, чтобы воспользоваться функцией DataTable
s RowFilter
, как это делает опубликованный код.Очевидно, как было сказано ранее, мы не будем использовать компаратор «LIKE», вместо этого используются операторы «<=» и «> =».
Чтобы выполнить это, мы ДОЛЖНЫ как-то перевернуть заданное значение * 1030.* диапазон «XX-XX» на два (2) int
с.Затем «добавьте» эти целые числа в DataTable
.Тогда будет легко отфильтровать таблицу, используя свойство RowFilter
и операторы меньше и больше, чем.Одна из проблем заключается в том, что для правильной настройки столбцов сетки потребуется дополнительная работа с нашей стороны, или эти два дополнительных столбца данных также будут отображаться.
Это можно сделать в «конструкторе» или вручную в коде.Не вдаваясь в подробности, полезно иметь в виду, что ЕСЛИ вы назначаете DataTable
в качестве источника данных для сетки и устанавливаете свойство AutoGenerateColumns
сетки false
... ТОЛЬКО только столбцы сетки с DataPropertyName
имен, которые «соответствуют» одному из имен столбцов DataTable
….В этом случае мы хотим, чтобы отображался только столбец AgeRange
со строками «XX-XX», остальные два новых столбца могут оставаться скрытыми от пользователя.Настройка столбца сетки вручную может выглядеть примерно так, как показано ниже, однако вы можете сделать это в конструкторе.ПРИМЕЧАНИЕ. Дизайнер не отображает свойство AutoGenerateColumns
, это необходимо сделать в своем коде.
private void AddGridColumn() {
DataGridViewTextBoxColumn col = new DataGridViewTextBoxColumn();
col.Name = "AgeRange";
col.DataPropertyName = "AgeRange";
col.HeaderText = "Age Range";
dgv1.Columns.Add(col);
}
Важным моментом является то, что DataPropertyName
ДОЛЖЕН совпадать с именем целевого столбца в DataTable
, в противном случае столбец не будет отображаться.
Далее идет построение новогоDataTable
.Этот метод дан оригиналу DataTable
.new DataTable
создается с тремя (3) столбцами, AgeRange-string (отображается), StartRange-int и EndRange-int. Начальный и конечный столбцы не будут отображаться. Как только эта новая таблица построена, цикл foreach
запускается по всем строкам в исходной таблице. Цифры строки из строки исходных таблиц «разбираются» на фактические числа и добавляются к новой DataTable
вместе с исходной строкой «диапазона». Этот метод может выглядеть примерно так: Ниже приводится вспомогательный метод, помогающий разбить строку возрастного диапазона и вернуть число.
private DataTable GetSplitTable(DataTable sourceTable) {
DataTable dt = new DataTable();
dt.Columns.Add("AgeRange", typeof(string));
dt.Columns.Add("StartRange", typeof(int));
dt.Columns.Add("EndRange", typeof(int));
foreach (DataRow row in sourceTable.Rows) {
int startValue = GetIntValue(row.ItemArray[0].ToString(), 0);
int endValue = GetIntValue(row.ItemArray[0].ToString(), 1);
dt.Rows.Add(row.ItemArray[0], startValue, endValue);
}
return dt;
}
private int GetIntValue(string rangeString, int index) {
string[] splitArray = rangeString.Split('-');
int value = 0;
int.TryParse(splitArray[index], out value);
return value;
}
Соединение всего этого может выглядеть так, как показано ниже. Обратите внимание, что событие нажатия кнопки проверяет, является ли текстовое поле пустым, и, если оно есть, удалит текущий фильтр, если он был применен.
private DataTable gridTable;
private DataTable splitTable;
public Form1() {
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) {
gridTable = GetTable();
FillTable(gridTable);
splitTable = GetSplitTable(gridTable);
AddGridColumn();
dgv1.AutoGenerateColumns = false;
dgv1.DataSource = splitTable;
textBox1.Text = "18";
}
private void FillTable(DataTable dt) {
dt.Rows.Add("0-18");
dt.Rows.Add("19-100");
dt.Rows.Add("0-100");
dt.Rows.Add("17-80");
dt.Rows.Add("15-75");
}
private DataTable GetTable() {
DataTable dt = new DataTable();
dt.Columns.Add("AgeRange", typeof(string));
return dt;
}
private void AddGridColumn() {
DataGridViewTextBoxColumn col = new DataGridViewTextBoxColumn();
col.Name = "AgeRange";
col.DataPropertyName = "AgeRange";
col.HeaderText = "Age Range";
dgv1.Columns.Add(col);
}
private void button1_Click(object sender, EventArgs e) {
string filterString = "";
DataView dv;
if (textBox1.Text != "") {
filterString = string.Format("StartRange <= {0} AND EndRange >= {0}", textBox1.Text);
}
dv = new DataView(splitTable);
dv.RowFilter = filterString;
dgv1.DataSource = dv;
}