sab669
sab669

Reputation: 4104

Dynamically setting a DataTable's RowFilter

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

Answers (1)

Baldrick
Baldrick

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

Related Questions