Hello,
This is very simple. You can use more than one condition in DataView's RowFilter property.
private DataTable _dt;
public Form1()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
LoadData();
LoadFilterData();
FilterData();
}
private void LoadData()
{
_dt = new DataTable();
_dt.Columns.Add("FName", typeof(string));
_dt.Columns.Add("LName", typeof(string));
_dt.Columns.Add("Age", typeof(int));
_dt.Columns.Add("City", typeof(string));
_dt.Rows.Add("Mike", "Brown", 25, "Berlin");
_dt.Rows.Add("James", "Blue", 35, "Accra");
_dt.Rows.Add("Philip", "Gay", 20, "London");
_dt.Rows.Add("Simon", "Black", 15, "Berlin");
_dt.Rows.Add("Martin", "Adjei", 45, "London");
_dt.Rows.Add("Peter", "Moore", 33, "Paris");
_dt.Rows.Add("Philip", "Gay", 51, "Berlin");
}
private void LoadFilterData()
{
cb1.Items.AddRange(new string[] { "All", "Berlin", "Accra", "London", "Paris" });
cb2.Items.AddRange(new string[] { "All", "James", "Martin", "Mike", "Peter", "Philip", "Simon" });
cb3.Items.AddRange(new string[] { "All", "Brown", "Gay", "Black", "Adjei", "Moore" });
for (int i = 0; i <= 100; i++)
{
cbFilterAgeFrom.Items.Add(i);
cbFilterAgeTo.Items.Add(i);
}
}
private void cb1_SelectedIndexChanged(object sender, EventArgs e)
{
FilterData();
}
private void cb2_SelectedIndexChanged(object sender, EventArgs e)
{
FilterData();
}
private void cb3_SelectedIndexChanged(object sender, EventArgs e)
{
FilterData();
}
private void cbFilterAgeFrom_SelectedIndexChanged(object sender, EventArgs e)
{
FilterData();
}
private void cbFilterAgeTo_SelectedIndexChanged(object sender, EventArgs e)
{
FilterData();
}
private void FilterData()
{
DataView dv = new DataView(_dt);
var cityFilter = string.IsNullOrWhiteSpace(cb1.Text) ? "All" : cb1.Text.Trim();
var fNameFilter = string.IsNullOrWhiteSpace(cb2.Text) ? "All" : cb3.Text.Trim();
var lNameFilter = string.IsNullOrWhiteSpace(cb3.Text) ? "All" : cb2.Text.Trim();
var ageFromFilter = string.IsNullOrWhiteSpace(cbFilterAgeFrom.Text) ? 0 : (int)cbFilterAgeFrom.SelectedItem;
var ageToFilter = string.IsNullOrWhiteSpace(cbFilterAgeTo.Text) ? 0 : (int)cbFilterAgeTo.SelectedItem;
var filterItems = new List<string>();
if (cityFilter != "All")
{
filterItems.Add(string.Format(" [City] = '{0}'", cityFilter));
}
if (fNameFilter != "All")
{
filterItems.Add(string.Format(" [FName] = '{0}'", fNameFilter));
}
if (lNameFilter != "All")
{
filterItems.Add(string.Format(" [LName] = '{0}'", lNameFilter));
}
if (ageFromFilter > 0)
{
filterItems.Add(string.Format(" [Age] >= {0}", ageFromFilter));
}
if (ageToFilter > 0)
{
filterItems.Add(string.Format(" [Age] <= {0}", ageToFilter));
}
if (filterItems.Count > 0)
{
var filter = string.Join(" AND ", filterItems);
MessageBox.Show(filter);
dv.RowFilter = filter;
}
dataGridView1.DataSource = dv;
}
More informations about RowFilter you can find here:
http://www.csharp-examples.net/dataview-rowfilter/[
^]
[Update - Answer for comment]
If you have more filter conditions there is a little bit simpler solution than my previous. I think that filtering age is better to filter between two values (from-to) than searching for exact value. So I've modified my answer and you should take some steps:
cb1 -> Combo filter for Cities
cb2 -> Combo filter for First names
cb3 -> Combo filter for Last names
Add two comboboxes for age filtering:
cbFilterAgeFrom,
cbFilterAgeTo -> Combo for filter age From-To
Don't forget to bind
SelectedIndexChanged event handler for new ComboBoxes.
Little explanation what is going here:
1. We are declaring List<string> to keep filter values for single fields. If you have selected City (i.e. Berlin) and AgeTo (i.e. 27) then our list will contain values like this:
[City] = 'Berlin'
[Age] <= 27
2. At the and of method
FilterData we are checking if list contains some items. If yes, then we are joining them to get one string for all
filterItems and we are adding
'AND' operator. So finally we get something like this:
[City] = 'Berlin' AND [Age] <= 27
And some links:
String.Join method[
^]
Collections in .NET[
^]
I hope you will find this useful :)