Reputation: 4104
I've got a DataTable with up to 20K rows being built during run time and then thrown into a DevExpress GridControl. I've added two filtering options that were initially being checked when the query was run... Meaning that if you wanted to change an option, you had to re-query and rebuild this massive DataTable and then remove the unwanted rows. This, obviously, was pretty inefficient and time consuming. I decided to make try to make this a little nicer by not making it rebuild the DataTable but simply filter it.
Initially, I came up with this god-awful looking chunk of code:
if (!cheBinObjFolders.Checked)
{
dt.DefaultView.RowFilter = "File NOT LIKE '*bin*'";
dt.DefaultView.RowFilter += " AND File NOT LIKE '*obj*'";
isFiltered = true;
}
else
{
if (!isFiltered)
{
dt.DefaultView.RowFilter = "File <> ''";
isFiltered = true;
}
else
dt.DefaultView.RowFilter += " AND File <> ''";
}
if (cheNormalFiles.Checked)
{
if (!isFiltered)
dt.DefaultView.RowFilter = "Status <> ''";
else
dt.DefaultView.RowFilter += " AND Status <> ''";
}
else
{
if (!isFiltered)
dt.DefaultView.RowFilter = "Status NOT LIKE '*Normal*'";
else
dt.DefaultView.RowFilter += " AND Status NOT LIKE '*Normal*'";
}
So I wanted to improve it, make it cleaner and easier if and when more filtering options get added. So I set the Tag property on my checkboxes to be the Column name ("File" or "Status") the checkbox would filter and wrote this:
//Empty quotes should be the actual right-hand side of the expression
foreach (Control c in this.Controls)
{
if (c is CheckEdit)
{
if (((CheckEdit)c).Checked && isFiltered)
dt.DefaultView.RowFilter += c.Tag.ToString() + "";
else if (((CheckEdit)c).Checked)
{
dt.DefaultView.RowFilter = c.Tag.ToString() + "";
isFiltered = true;
}
else
dt.DefaultView.RowFilter = c.Tag.ToString() + "<> ";
}
}
However, I have no idea how to dynamically come up with the right hand side of the expression like this. Any ideas what I could do? I'm kind of thinking I should just subclass this Checkbox control and add 2 string properties; "Field" and "Filter" then just use those to build my filter. Is there a better way?
Edit: Alright, I came up with this with your suggestions/advice:
private string BuildTableFilter()
{
foreach (Control control in this.Controls)
{
if (control is CheckEdit && control.Tag != null)
{
var c = (CheckEdit)control;
if (c.Checked)
{
if (!filters.Contains(c.Tag.ToString()))
filters.Add(c.Tag.ToString());
}
else
filters.Remove(c.Tag.ToString());
}
}
return String.Join(" AND ", filters.ToArray());
}
So all I need to do in the future is just add the proper Filter expression to the Tag. Unfortunately, with so many rows it still locks up the UI briefly (5 seconds maybe), so I'll need to tackle that next...
Upvotes: 1
Views: 1856
Reputation: 11840
You probably want to build the query using a list of statements (in this case, the Tag would be the filter statement for that control);
var filterTerms = new List<string>();
foreach (Control c in this.Controls)
{
if (c is CheckEdit)
{
if (((CheckEdit)c).Checked)
{
filterTerms.Add(c.Tag.ToString());
}
}
}
dt.DefaultView.RowFilter = string.Join(" AND ", filterTerms);
Upvotes: 3