我认为您无法使用“LIKE”比较器执行此操作,因为您要查找的值是“数字”。要获得您正在寻找的过滤器,您需要一个带有“>=”和“
一种“hacky”方法是创建一个返回新DataTable 的方法,其中仅包含落入给定目标范围内的行。为了帮助完成这项工作,第二种方法采用int(我们正在寻找的目标值)和DataRowView(我们正在比较“目标”值的AgeRange)。此“AgeRange”将位于行的第一列中。这里我们简单地取那个字符串范围(“0-18”)和目标值(“18”)来看看这个目标值是否在这个范围内,然后根据结果返回真或假。这可以使用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
第一种方法有效;但是,我猜如果有大量数据和大量过滤,这可能会成为性能问题。因此,在这种方法中,一开始就采取了额外的步骤来利用DataTables RowFilter 功能,正如发布的代码所做的那样。显然如前所述,我们不会使用“LIKE”比较器,而是使用“=”运算符。
为了实现这一点,我们必须以某种方式将给定的string 范围“XX-XX”转换为两 (2) 个ints。然后将这些整数“添加”到DataTable。然后使用RowFilter 属性和小于和大于运算符过滤表将很容易。一个问题是我们需要“额外”的工作来正确设置网格的列,否则这额外的两列数据也会显示出来。
这可以在“设计器”中完成,也可以在代码中手动完成。无需过多详细说明,请记住,如果您将 DataTable 作为数据源分配给网格,并且将网格 AutoGenerateColumns 属性设置为 false... 那么只有带有 @ 的网格列将显示与DataTable 列名之一“匹配”的 987654343@ 名称。在这种情况下,我们只希望显示带有“XX-XX”字符串的AgeRange 列,其他两个新列可以对用户保持隐藏。手动设置网格列可能如下所示,但是您可以在设计器中执行此操作。注意:设计器不会显示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。使用三 (3) 列、AgeRange-string(显示)、StartRange-int 和 EndRange-int 创建新的 DataTable。将不显示开始列和结束列。一旦构建了这个新表,就会开始一个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;
}