有个项目,客户要求表格要像Excel那样具有根据列的复杂筛选功能,而且最好不要改变太多原先的使用习惯。
上网搜了一下,大部分的都是把整列绑定到一个combobox上,覆盖到列标题上,从而达到简单的筛选功能。
仔细研究了下Excel的复杂筛选,仅靠DataGridView的右键功能不太好完全实现,于是就想到用一个panel来当筛选面板。
===================================================================
新建一个项目,form1中拖入一个datagridview,一个panel,一个statusStrip。
panel中如图所示放上2个label,7个button,3个combobox,1个listbox。
statusStrip中放入3个toolStripStatusLabel。
点击“升序”或者“降序”可以直接根据这一列来进行排序。
在筛选条件中,第一个combobox来选择“与”或者“或”,第二个combobox用来显示等于、大于、小于、包含等等,第三个combobox用来显示当前列所有非重复内容。
点击“添加条件”可以把上面的筛选条件添加到listbox中,选中listbox中的一个条件,点击“移除条件”可以移除该条件。
最后点击“确定”执行筛选,点击“取消”撤销本次所做的操作。
toolStripStatusLabel1用来显示按某一列升序或者降序排列。
toolStripStatusLabel2用来显示从N条数据中筛选到了M条数据。
toolStripStatusLabel3用来显示筛选的语句。
--------------------------------------------------
1、定义5个全局变量
DataTable dt; DataView dv; int row_total;//总行数 int row_select; //筛选后行数 string[] str_ltb;//存储筛选条件数组
2、给datagridview填入数据并初始化一些数据private void Form1_Load(object sender, EventArgs e) { dt = new DataTable(); dt.Columns.Add("ID", Type.GetType("System.Int32")); dt.Columns[0].AutoIncrement = true; //列值自动递增 dt.Columns[0].AutoIncrementSeed = 1; //起始值 dt.Columns[0].AutoIncrementStep = 1; //步长 dt.Columns.Add("Name", Type.GetType("System.String")); dt.Columns.Add("Birthday", Type.GetType("System.String")); dt.Columns.Add("Address", Type.GetType("System.String")); dt.Columns.Add("Salary", Type.GetType("System.Int32")); dt.Rows.Add(new object[] { null, "张一", "1980-01-01", "北京", 15000 }); dt.Rows.Add(new object[] { null, "张二", "1981-02-28", "上海", 20000 }); dt.Rows.Add(new object[] { null, "张三", "1982-03-18", "北京", 10000 }); dt.Rows.Add(new object[] { null, "张四", "1983-04-01", "河北", 5000 }); dt.Rows.Add(new object[] { null, "张五", "1984-05-14", "北京", 8000 }); dt.Rows.Add(new object[] { null, "李一", "1985-10-01", "广州", 11000 }); dt.Rows.Add(new object[] { null, "李二", "1986-09-07", "上海", 18000 }); dt.Rows.Add(new object[] { null, "李三", "1987-06-10", "北京", 20000 }); dt.Rows.Add(new object[] { null, "李四", "1988-04-01", "广州", 5000 }); dt.Rows.Add(new object[] { null, "李五", "1989-03-05", "北京", 7000 }); dt.Rows.Add(new object[] { null, "王一", "1983-01-09", "广州", 15000 }); dt.Rows.Add(new object[] { null, "王二", "1985-12-03", "上海", 30000 }); dt.Rows.Add(new object[] { null, "王三", "1987-08-22", "北京", 5000 }); dt.Rows.Add(new object[] { null, "王四", "1989-01-15", "河北", 3000 }); dt.Rows.Add(new object[] { null, "王五", "1989-05-20", "北京", 11000 }); //dgv.DataSource = dt; dgv.Dock = DockStyle.Fill; row_total = dt.Rows.Count; dv = dt.DefaultView; dgv.DataSource = dv; row_select = row_total; //禁止点击列标题自动排序 for (int i = 0; i < dgv.Columns.Count; i++) { dgv.Columns[i].SortMode = DataGridViewColumnSortMode.NotSortable; } pl_dgv_extend.Visible = false; toolStripStatusLabel1.Text = "按 ID 列升序排列"; toolStripStatusLabel2.Text = "在 " + row_total + " 条数据中找到 " + row_select + " 个"; toolStripStatusLabel3.Text = ""; }
3、点击dgv列标题,panel显示,并根据列标题的不同位置,对应显示到相应的位置private void dgv_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) { int dLeft, dTop; //获取dgv列标题位置相对坐标 Rectangle range = dgv.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, false); //计算pl_dgv_extend位置坐标 dLeft = range.Left + dgv.Left; dTop = range.Top + dgv.Top + range.Height; //设置pl_dgv_extend位置,超出框体宽度时,和dgv右边对齐 if (dLeft + pl_dgv_extend.Width > this.Width) { pl_dgv_extend.SetBounds(dgv.Width - pl_dgv_extend.Width, dTop, pl_dgv_extend.Width, pl_dgv_extend.Height); } else { pl_dgv_extend.SetBounds(dLeft, dTop, pl_dgv_extend.Width, pl_dgv_extend.Height); } //设置cb_condition下拉菜单内容 cb_condition.Items.Clear(); for (int i = 0; i < dgv.Rows.Count; i++) { bool isfind = false; for (int j = 0; j < cb_condition.Items.Count; j++) { if (cb_condition.Items[j].ToString() == dgv.Rows[i].Cells[e.ColumnIndex].Value.ToString()) { isfind = true; j = cb_condition.Items.Count;//break } } if (!isfind) { cb_condition.Items.Add(dgv.Rows[i].Cells[e.ColumnIndex].Value.ToString()); } } pl_dgv_extend.Visible = true; lb_columnname.Text = dgv.Columns[e.ColumnIndex].Name; //初始化选择项 cb_andor.SelectedIndex = 0; cb_operator.SelectedIndex = 0; cb_condition.Text = ""; //存储现有的筛选条件选项 if (ltb_condition.Items.Count == 0) { str_ltb = null; } else { str_ltb = new string[ltb_condition.Items.Count]; ltb_condition.Items.CopyTo(str_ltb, 0); } }
4、升序降序代码private void bt_asc_Click(object sender, EventArgs e) { dv.Sort = lb_columnname.Text + " asc"; toolStripStatusLabel1.Text = "按 " + lb_columnname.Text + " 列升序排列"; pl_dgv_extend.Visible = false; } private void bt_desc_Click(object sender, EventArgs e) { dv.Sort = lb_columnname.Text + " desc"; toolStripStatusLabel1.Text = "按 " + lb_columnname.Text + " 列降序排列"; pl_dgv_extend.Visible = false; }
5、添加筛选条件private void bt_add_Click(object sender, EventArgs e) { //空值判断 if (cb_operator.SelectedItem == null || cb_condition.Text.Trim() == "") { MessageBox.Show("请选择条件!"); return; } if (cb_andor.SelectedItem == null && ltb_condition.Items.Count > 0) { MessageBox.Show("请选择条件!"); return; } //文字转运算符 string str_andor = "", str_operator = ""; if (ltb_condition.Items.Count > 0) { if (cb_andor.SelectedItem == null) str_andor = ""; else if (cb_andor.SelectedItem.ToString() == "或") str_andor = "or "; else str_andor = "and "; } if (cb_operator.SelectedItem.ToString() == "等于") str_operator = "= "; else if (cb_operator.SelectedItem.ToString() == "大于") str_operator = "> "; else if (cb_operator.SelectedItem.ToString() == "大于等于") str_operator = ">= "; else if (cb_operator.SelectedItem.ToString() == "小于") str_operator = "< "; else if (cb_operator.SelectedItem.ToString() == "小于等于") str_operator = "<= "; else str_operator = "like "; //筛选条件添加到listbox if (cb_operator.SelectedItem.ToString() == "包含") { ltb_condition.Items.Add(str_andor + lb_columnname.Text + " " + str_operator + "'*" + cb_condition.Text.Trim() + "*'"); } else { ltb_condition.Items.Add(str_andor + lb_columnname.Text + " " + str_operator + "'" + cb_condition.Text.Trim() + "'"); } //初始化筛选条件 cb_andor.SelectedIndex = 0; cb_operator.SelectedIndex = 0; cb_condition.Text = ""; }
6、移除筛选条件private void bt_remove_Click(object sender, EventArgs e) { if (ltb_condition.SelectedItem == null) { MessageBox.Show("请选择需要移除的项!"); return; } int rownum = ltb_condition.SelectedIndex; ltb_condition.Items.RemoveAt(rownum); //如果移除了第一项并且移除后listbox项数目大于0 //把第一项开头的and或者or去掉 if (ltb_condition.Items.Count > 0 && rownum == 0) { string first = ltb_condition.Items[0].ToString(); string result; if (first.Substring(0, 2) == "or") { result = first.Substring(2, first.Length - 3); } else { result = first.Substring(3, first.Length - 4); } ltb_condition.Items.RemoveAt(0); ltb_condition.Items.Insert(0, result); } }
7、清除所有筛选条件private void bt_clear_Click(object sender, EventArgs e) { if (MessageBox.Show("是否要移除所有筛选条件?", "警告", MessageBoxButtons.YesNo) == DialogResult.Yes) { ltb_condition.Items.Clear(); } dv.RowFilter = ""; //清空筛选条件 pl_dgv_extend.Visible = false; row_select = row_total; toolStripStatusLabel2.Text = "在 " + row_total + " 条数据中找到 " + row_select + " 个"; toolStripStatusLabel3.Text = ""; }
8、确认,执行筛选程序private void bt_ok_Click(object sender, EventArgs e) { if (ltb_condition.Items.Count == 0) { dv.RowFilter = ""; toolStripStatusLabel3.Text = ""; } else { for (int i = 0; i < ltb_condition.Items.Count; i++) { if (i == 0) toolStripStatusLabel3.Text = ltb_condition.Items[0].ToString(); else toolStripStatusLabel3.Text += " " + ltb_condition.Items[i].ToString(); } dv.RowFilter = toolStripStatusLabel3.Text; } pl_dgv_extend.Visible = false; row_select = dv.Count; toolStripStatusLabel2.Text = "在 " + row_total + " 条数据中找到 " + row_select + " 个"; }
9、取消,回滚操作private void bt_cancle_Click(object sender, EventArgs e) {//回滚操作 ltb_condition.Items.Clear(); if (str_ltb != null) ltb_condition.Items.AddRange(str_ltb); pl_dgv_extend.Visible = false; }
--------------------------------------------------以上就是所有的代码了,新手,大家就将就着看吧。下面来看一下实际运行效果。
=========================================================
1、运行界面
2、点击列标题
3、点击边上的列标题,panel自动调整位置
4、按salary升序排列
5、填写筛选条件
6、填入两个条件
7、查询结果,在下方状态条显示筛选条目
8、多加一些条件
9、最终效果
注:由于toolStripStatusLabel的内容文字一旦超过最大宽度,该控件就会被隐藏,所以我把窗体拉长了点。至于怎么让它部分显示,没有查到。其实下面这个状态条完全可以用panel+label来实现,这样文字一旦超出label范围,就可以部分显示了。
/************************************************************* * * 来自于C#初学者——phoenix * 2015年5月22日 * http://blog.csdn.net/phoenix36999 * * **********************************************************/