上一篇 Winform系列——好看的DataGridView折叠控件 中主要介绍了DataGridview的表格多级折叠功能。这章主要介绍下最近封装的另一个DataGridview表格高级过滤的功能。此功能也是参照codeproject上面的源码改写的,代码可能有源码的内容,也有本人改写过的,所以看上去可能有点乱。废话不多说,上图:

1、一般的DataGridview效果:

2、增加了列上面右键效果:

3、升序和降序就没什么说的了,看看点击过滤的效果吧:

4、取消某一个字段过滤的方式有两种:

5、取消所有字段的过滤:

大致效果就如上了。代码有点乱,如果有时间我会整理下,有兴趣的可以看看。

1、向外暴露的使用类:这个类主要功能是通过构造函数 public DgvFilterManager(DataGridView dataGridView, bool autoCreateFilters){}将DataGridview对象传进来,然后再给DataGridview增加事件和方法实现的。代码如下:

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Data;
using System.ComponentModel;
using Ewin.Client.Frame;
using Ewin.Client.Frame.Controls;
using System.Collections;
using System.Reflection; namespace Ewin.Client.Frame.UcGrid
{
public class DgvFilterManager
{ #region PRIVATE FIELDS private DgvBaseFilterHost mFilterHost; // The host UserControl to popup
private DataGridView mDataGridView; // The DataGridView to which apply filtering
private DataView mBoundDataView; // The DataView to which the DataGridView is bound
BindingSource mBindingSource; // The BindingSource, if any, to which the DataGridView is bound private string mBaseFilter = ""; // Developer provided filter expression
private int mCurrentColumnIndex = -; // Column Index of currently visibile filter private List<DgvBaseColumnFilter> mColumnFilterList; // List of ColumnFilter objects
private bool mAutoCreateFilters = true;
private bool mFilterIsActive = false; ContextMenuStrip oMenuStrip;
#endregion #region EVENTS /// <summary>
/// Occurs when a <i>column filter</i> instance for a column is about to be automatically created.
/// </summary>
/// <remarks>
/// Using this event you can set the <see cref="ColumnFilterEventArgs.ColumnFilter"/>
/// property to force the <see cref="DgvBaseColumnFilter"/> specialization to use for the
/// column.
/// This event is raised only if <see cref="DgvFilterManager.AutoCreateFilters"/> is true.
/// </remarks>
public event ColumnFilterEventHandler ColumnFilterAdding; /// <summary>
/// Occurs when a <i>column filter</i> instance is created.
/// This event is raised only if <see cref="DgvFilterManager.AutoCreateFilters"/> is true.
/// </summary>
public event ColumnFilterEventHandler ColumnFilterAdded; /// <summary>
/// Occurs when the popup is about to be shown
/// </summary>
/// <remarks>
/// Use this event to customize the popup position. Set the Handled property of the event argument to <c>true</c>.
/// </remarks>
public event ColumnFilterEventHandler PopupShowing; #endregion #region CONSTRUCTORS /// <summary>
/// Initializes a new instance of the <see cref="DgvFilterManager"/> class.
/// </summary>
public DgvFilterManager() { } /// <summary>
/// Initializes a new instance of the <see cref="DgvFilterManager"/> class.
/// </summary>
/// <param name="dataGridView">The <b>DataGridView</b> to which attach filtering capabilities</param>
/// <param name="autoCreateFilters">if set to <c>true</c> automatically creates a <i>column filter</i> for each column</param>
public DgvFilterManager(DataGridView dataGridView, bool autoCreateFilters)
{
this.mAutoCreateFilters = autoCreateFilters;
this.DataGridView = dataGridView;
} /// <summary>
/// Initializes a new instance of the <see cref="DgvFilterManager"/> class.
/// </summary>
/// <param name="dataGridView">The <b>DataGridView</b> to which attach filtering capabilities.</param>
public DgvFilterManager(DataGridView dataGridView) : this(dataGridView, true) { } #endregion #region PROPERTIES /// <summary>
/// Gets or sets a value indicating whether the manager must create <i>column filters</i>.
/// </summary>
/// <value><c>true</c> by default.</value>
public bool AutoCreateFilters
{
get { return mAutoCreateFilters; }
set { mAutoCreateFilters = value; }
} /// <summary>
/// Gets and sets the <i>filter host</i> to use.
/// </summary>
/// <remarks>
/// The default <i>filter host</i> is an instance of <see cref="DgvFilterHost"/>
/// </remarks> public DgvBaseFilterHost FilterHost
{
get
{
if (mFilterHost == null)
{
// If not provided, use the default FilterHost
FilterHost = new DgvFilterHost();
//FilterHost.AllowDrop = true;
//FilterHost.Popup.MouseDown += FilterHost_MouseDown; }
return mFilterHost;
}
set
{
mFilterHost = value;
// initialize FilterManager to this object
mFilterHost.FilterManager = this;
mFilterHost.Popup.Closed += new ToolStripDropDownClosedEventHandler(Popup_Closed); }
} void oForm_DragEnter(object sender, DragEventArgs e)
{
//当Button被拖拽到WinForm上时候,鼠标效果出现
if ((e.Data.GetDataPresent(typeof(DgvFilterHost))))
{
e.Effect = DragDropEffects.Copy;
}
} void oForm_DragDrop(object sender, DragEventArgs e)
{
//拖放完毕之后,自动生成新控件
//Button btn = new Button();
//btn.Size = Button1.Size;
//btn.Location = this.PointToClient(new Point(e.X, e.Y));
////用这个方法计算出客户端容器界面的X,Y坐标。否则直接使用X,Y是屏幕坐标
//this.Controls.Add(btn);
//btn.Text = "按钮" + count.ToString();
//count = count + 1;
} void FilterHost_MouseDown(object sender, MouseEventArgs e)
{
//左键的话,标志位为true(表示拖拽开始)
if ((e.Button == System.Windows.Forms.MouseButtons.Left))
{
FilterHost.DoDragDrop(FilterHost, DragDropEffects.Copy | DragDropEffects.Move);
//形成拖拽效果,移动+拷贝的组合效果
}
} /// <summary>
/// Gets and sets the DataGridView to which apply filtering capabilities.
/// </summary>
/// <remarks>
/// <para>
/// When a <b>DataGridView</b> is attached, the manager perform the following actions:
/// <ul>
/// <li>it creates a <i>filter host</i>, that is an instance of the <b>DgvFilterHost</b> class. If you previously provided a
/// <i>filter host</i>, this step is skipped.</li>
/// <li>it creates an array of <b>DgvBaseColumnFilter</b>, one per column, and initializes each element to a specialization
/// of <b>DgvBaseColumnFilter</b>. If <see cref="DgvFilterManager.AutoCreateFilters"/> is false, this step is skipped.
/// </li>
/// </ul>
/// </para>
/// <para>
/// You can force a specific <i>column filter</i> for a certain column, intervening in this process through the events
/// <see cref="DgvFilterManager.ColumnFilterAdding"/> and <see cref="DgvFilterManager.ColumnFilterAdded"/>. You can also intervene, after the entire process, replacing
/// a <i>column filter</i> instance in the array with another instance you created.
/// </para>
/// </remarks>
public DataGridView DataGridView
{
get
{
return mDataGridView;
}
set
{
mDataGridView = value;
mColumnFilterList = new List<DgvBaseColumnFilter>(mDataGridView.Columns.Count);
FindDataView();
mDataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
mDataGridView.CellMouseClick += new DataGridViewCellMouseEventHandler(mDataGridView_CellMouseClick);
mDataGridView.CellPainting += new DataGridViewCellPaintingEventHandler(mDataGridView_CellPainting);
mDataGridView.ColumnAdded += new DataGridViewColumnEventHandler(mDataGridView_ColumnAdded);
mDataGridView.ColumnRemoved += new DataGridViewColumnEventHandler(mDataGridView_ColumnRemoved);
if (mDataGridView == null) return;
foreach (DataGridViewColumn c in mDataGridView.Columns)
{
mColumnFilterList.Add(null);
CreateColumnFilter(c);
}
}
} /// <summary>
/// Gets and sets developer provided filter expression. This expression
/// will be "merged" with end-user created filters.
/// </summary>
/// <value>The base filter.</value> public string BaseFilter
{
get { return mBaseFilter; }
set { mBaseFilter = value; RebuildFilter(); }
} /// <summary>
/// Gets or sets the <i>column filter</i> control related to the ColumnIndex
/// </summary>
/// <param name="ColumnIndex">The index of the <b>DataGridView</b> column</param>
/// <returns>the <b>DgvBaseColumnFilter</b> related to the <b>DataGridView</b> column</returns>
/// <remarks>
/// This indexer allow you to get and set the <i>column filter</i> instance for the column.
/// You can set one of the standard <i>column filter</i> implementation or an instance
/// of your own <b>DgvBaseFilterColumn</b> specialization.
/// </remarks>
public DgvBaseColumnFilter this[int ColumnIndex]
{
get { return mColumnFilterList[ColumnIndex]; }
set
{
mColumnFilterList[ColumnIndex] = value;
value.Init(this, FilterHost, mDataGridView.Columns[ColumnIndex], mBoundDataView);
}
} /// <summary>
/// Gets or sets the <i>column filter</i> control related to the ColumnName
/// </summary>
/// <param name="ColumnName">The name of the <b>DataGridView</b> column</param>
/// <returns>the DgvBaseColumnFilter related to the <b>DataGridView</b> column</returns>
/// <remarks>
/// This indexer allow you to get and set the <i>column filter</i> instance for the column.
/// You can set one of the standard <i>column filter</i> implementation or an instance
/// of your own <b>DgvBaseFilterColumn</b> specialization.
/// </remarks>
public DgvBaseColumnFilter this[string ColumnName]
{
get { return mColumnFilterList[mDataGridView.Columns[ColumnName].Index]; }
set
{
this[mDataGridView.Columns[ColumnName].Index] = value;
}
} #endregion #region DATAGRIDVIEW EVENT HANDLERS private void mDataGridView_ColumnRemoved(object sender, DataGridViewColumnEventArgs e)
{
mColumnFilterList.RemoveAt(e.Column.Index);
} private void mDataGridView_ColumnAdded(object sender, DataGridViewColumnEventArgs e)
{
FindDataView();
mColumnFilterList.Insert(e.Column.Index, null);
CreateColumnFilter(e.Column);
} #region 新增修改代码 Edit By yangxiaojun System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Resource)); /// <summary>
/// Shows the popup when user right-clicks a column header
/// </summary>
/// <param name="sender">The event source.</param>
/// <param name="e">The <see cref="System.Windows.Forms.DataGridViewCellMouseEventArgs"/> instance containing the event data.</param>
protected virtual void mDataGridView_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{ //var oForm = mDataGridView.FindForm();
//oForm.AllowDrop = true;
//oForm.DragDrop += oForm_DragDrop;
//oForm.DragEnter += oForm_DragEnter;
if (e.Button == MouseButtons.Right && e.RowIndex == - && e.ColumnIndex > -)
{
if (oMenuStrip == null)
{
oMenuStrip = new ContextMenuStrip();
oMenuStrip.Size = new System.Drawing.Size(, );
}
oMenuStrip.Items.Clear();
//0.升序菜单
var oSortClientEnvent = new EventHandler(mMenuStripSort_Click);
var oToolAscding = new MyToolStripMenuItem("升序", ((System.Drawing.Image)(resources.GetObject("ascending"))), oSortClientEnvent);
oToolAscding.Name = "toolscriptmenuitemasc";
oToolAscding.Size = new System.Drawing.Size(, );
oToolAscding.SortKey = this.mDataGridView.Columns[e.ColumnIndex].Name;
oToolAscding.SortDirection = ListSortDirection.Ascending;
oMenuStrip.Items.Add(oToolAscding); //1.降序菜单
var oToolDescending = new MyToolStripMenuItem("降序", ((System.Drawing.Image)(resources.GetObject("descending"))), oSortClientEnvent);
oToolDescending.Name = "toolscriptmenuitemdesc";
oToolDescending.Size = new System.Drawing.Size(, );
oToolDescending.SortKey = this.mDataGridView.Columns[e.ColumnIndex].Name;
oToolDescending.SortDirection = ListSortDirection.Descending;
oMenuStrip.Items.Add(oToolDescending); //2.分割线
var oSeparator = new System.Windows.Forms.ToolStripSeparator();
oMenuStrip.Items.Add(oSeparator); //3.过滤菜单
var oToolFilter = new MyToolStripMenuItem("过滤...", ((System.Drawing.Image)(resources.GetObject("Filter_Image"))), new EventHandler(mMenuStripFilter_Click));
oToolFilter.ColumnIndex = e.ColumnIndex;
oToolFilter.ColumnName = this.mDataGridView.Columns[e.ColumnIndex].Name;
oMenuStrip.Items.Add(oToolFilter); //4.取消过滤菜单
var oToolCancelFilter = new MyToolStripMenuItem("取消过滤", ((System.Drawing.Image)(resources.GetObject("Filter_Clear_Image"))), new EventHandler(mMenuStripCancelFilter_Click));
oToolCancelFilter.ColumnIndex = e.ColumnIndex;
oToolCancelFilter.ColumnName = this.mDataGridView.Columns[e.ColumnIndex].Name;
oMenuStrip.Items.Add(oToolCancelFilter);
Rectangle r = mDataGridView.GetCellDisplayRectangle(e.ColumnIndex, -, false);
oMenuStrip.Show(mDataGridView, r.X + e.X, r.Y + e.Y);
//ShowPopup(e.ColumnIndex);
}
} //菜单单击排序事件
protected virtual void mMenuStripSort_Click(object sender, EventArgs e)
{
//MessageBox.Show("测试");
var oToolScript = (((MyToolStripMenuItem)sender));
this.mDataGridView.Sort(this.mDataGridView.Columns[oToolScript.SortKey], oToolScript.SortDirection);
} //菜单单击过滤事件
protected virtual void mMenuStripFilter_Click(object sender, EventArgs e)
{
Ewin.Client.Frame.Forms.EwinTaskWindow.ShowTaskWindow("Edit Filter", FilterHost); var oToolScript = (((MyToolStripMenuItem)sender)); if (mColumnFilterList[oToolScript.ColumnIndex] == null) return; // non-data column
SetCurrentFilterIndex(oToolScript.ColumnIndex);
//FilterHost.Popup.Show(mDataGridView, 480, 150); // show the filterhost popup near the column
FilterHost.Popup.Focus();
var lstCols = mDataGridView.Columns;
var lstDataSource = new List<object>();
foreach (DataGridViewColumn oCol in lstCols)
{
var oColHeadName = oCol.HeaderText.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
var comboitem = new { Value = oCol.Name, Text = oColHeadName[] };
lstDataSource.Add(comboitem);
//lstDataSource.Add(oCol.Name);
}
FilterHost.ComboBoxColumns.DataSource = lstDataSource;
FilterHost.ComboBoxColumns.DisplayMember = "Text";
FilterHost.ComboBoxColumns.ValueMember = "Value";
FilterHost.ComboBoxColumns.SelectedValueChanged += ComboBoxColumns_SelectedValueChanged;
FilterHost.ComboBoxColumns.SelectedValue = oToolScript.ColumnName; //显示过滤表达式
SetFilterExpression();
} //取消过滤菜单事件
protected virtual void mMenuStripCancelFilter_Click(object sender, EventArgs e)
{
var oToolScript = (((MyToolStripMenuItem)sender)); //0.指定当前过滤列索引
if (mColumnFilterList[oToolScript.ColumnIndex] == null) return; // non-data column
SetCurrentFilterIndex(oToolScript.ColumnIndex); //1.使当前过滤列失效,即Active=false;
ActivateFilter(false);
} //删除过滤条件图标的点击事件
private void oPicBox_Click(object sender, EventArgs e)
{
//1.根据过来字段找到过滤字段索引
var oPicBox = (EwinImgButton)sender;
var iFilterIndex = GetFilterIndexByFilterName(oPicBox.Tag.ToString());
if (iFilterIndex == -) return;
//2.设置当前过滤索引
SetCurrentFilterIndex(iFilterIndex); //3.将当前过滤列的Active设为false
ActivateFilter(false); //4.设置过滤表达式
SetFilterExpression();
} //选择列的选择事件
protected virtual void ComboBoxColumns_SelectedValueChanged(object sender, EventArgs e)
{
var oSelectedValue = ((ComboBox)sender).SelectedValue.ToString();
var iFilterIndex = GetFilterIndexByFilterName(oSelectedValue);
if (iFilterIndex == -) return;
SetCurrentFilterIndex(iFilterIndex);
} //根据过滤列的名称得到过滤列的列索引
private int GetFilterIndexByFilterName(string strFilterName)
{
int iRes = -;
var lstCols = mDataGridView.Columns;
foreach (DataGridViewColumn oCol in lstCols)
{
if (oCol.Name == strFilterName ||oCol.HeaderText.Contains(strFilterName))
{
if (mColumnFilterList[oCol.Index] == null) return -; // non-data column
iRes = oCol.Index;
break;
}
} return iRes;
} //设置当前过滤索引
private void SetCurrentFilterIndex(int iIndex)
{
int OldColumnIndex = mCurrentColumnIndex;
mCurrentColumnIndex = iIndex;
FilterHost.CurrentColumnFilter = mColumnFilterList[iIndex];
try
{
//use "try" because old column could have been removed
mDataGridView.InvalidateCell(OldColumnIndex, -);
}
catch { }
} //显示过滤表达式
public void SetFilterExpression()
{
var arrFilterText = new List<string>();
foreach (DgvBaseColumnFilter CF in mColumnFilterList)
{
if (CF == null) continue;
if (CF.Active && CF.FilterExpression != "")
{
arrFilterText.Add(CF.FilterCaption.Replace("\n", " ").Replace("<> ?", "<> NULL").Replace("= ?", "= NULL"));
}
} //var strRowFilterText = mBoundDataView.RowFilter.Contains("1=1 AND") ? mBoundDataView.RowFilter.Replace("1=1 AND", string.Empty) : mBoundDataView.RowFilter;
//var arrFilterText = strRowFilterText.Split(new string[] { " AND " }, StringSplitOptions.RemoveEmptyEntries);
var y = ;
//0.先清空表达式再重新绘制控件
FilterHost.PanelFilterText.Controls.Clear();
var panelFilterText = new EwinPanel();
panelFilterText.AutoScroll = true;
panelFilterText.HorizontalScrollbar = true;
panelFilterText.HorizontalScrollbarBarColor = true;
panelFilterText.HorizontalScrollbarHighlightOnWheel = false;
panelFilterText.HorizontalScrollbarSize = ;
panelFilterText.Location = new System.Drawing.Point(, );
panelFilterText.Name = "panelFilterText1";
panelFilterText.Size = new System.Drawing.Size(, );
panelFilterText.VerticalScrollbar = true;
panelFilterText.VerticalScrollbarBarColor = true;
panelFilterText.VerticalScrollbarHighlightOnWheel = false;
panelFilterText.VerticalScrollbarSize = ;
panelFilterText.ShowBorder = false;
foreach (var strText in arrFilterText)
{
//1.新增panel
var oPanelText = new EwinPanel();
oPanelText.Name = "oPanelText" + y;
oPanelText.Location = new System.Drawing.Point(, y);
oPanelText.Size = new System.Drawing.Size(, );
oPanelText.ShowBorder = false; //2.向panel里面新增显示表达式的label
var oLabelText = new EwinLabel();
oLabelText.Cursor = Cursors.Hand;
oLabelText.ForeColor = Color.BlueViolet;
oLabelText.AutoSize = true;
oLabelText.Location = new System.Drawing.Point(, );
oLabelText.Name = "label_filtertext" + y;
oLabelText.Text = strText.Trim().Trim(new char[] { '(', ')' });
oLabelText.Size = new System.Drawing.Size(oLabelText.Text.Length * , ); //3.向panel里面新增删除图标
var oPicBox = new EwinImgButton();
oPicBox.Image = ((System.Drawing.Image)(resources.GetObject("Close_tab")));
oPicBox.Cursor = Cursors.Hand;
oPicBox.Location = new Point(oLabelText.Width + , );
oPicBox.Size = new System.Drawing.Size(, );
var otooltip = new System.Windows.Forms.ToolTip();
otooltip.SetToolTip(oPicBox, "删除过滤条件");
oPicBox.Click += oPicBox_Click;
oPicBox.Tag = oLabelText.Text.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries)[];
oPanelText.Controls.Add(oPicBox);
oPanelText.Controls.Add(oLabelText);
y = y + ;
panelFilterText.Controls.Add(oPanelText);
//FilterHost.PanelFilterText.Controls.Add(oPanelText);
}
FilterHost.PanelFilterText.Controls.Add(panelFilterText);
panelFilterText.Invalidate();
}
#endregion //Based on filters state, call the appropriate protected paint helpers
private void mDataGridView_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
if (e.RowIndex != -) return; //skip if it is not the header row //1.绘制e.RowIndex == -1 && e.ColumnIndex == -1处的过滤图标
//Cell Origin
if (e.RowIndex == - && e.ColumnIndex == - && mFilterIsActive)
{
OnFilteredGridPaint(sender, e);
return;
} //2.如果过滤框显示,绘制过滤列表头的边框
//if (FilterHost.Popup.Visible)
//{
// OnHighlightedColumnPaint(sender, e);
//} //3.绘制过滤列表头的样式
if (e.ColumnIndex == -) return;
if (mColumnFilterList[e.ColumnIndex] != null && mColumnFilterList[e.ColumnIndex].Active)
{
OnFilteredColumnPaint(sender, e);
}
} /// <summary>
/// Paints a funnel icon in the cell origin when some column is filtered.
/// </summary>
/// <param name="sender">The sender</param>
/// <param name="e">The <see cref="System.Windows.Forms.DataGridViewCellPaintingEventArgs"/> instance containing the event data.</param>
/// <remarks>
/// Override this method to provide your own painting
/// </remarks>
protected virtual void OnFilteredGridPaint(object sender, DataGridViewCellPaintingEventArgs e)
{
e.Graphics.FillRectangle(Brushes.White, e.CellBounds);
e.Paint(e.CellBounds, e.PaintParts & ~DataGridViewPaintParts.Background);
Rectangle r = new Rectangle(e.CellBounds.X + , e.CellBounds.Y + , e.CellBounds.Width - , e.CellBounds.Height - );
e.Graphics.DrawImage(FunnelPicture, (e.CellBounds.Width - FunnelPicture.Width) / , (e.CellBounds.Height - FunnelPicture.Height) / , FunnelPicture.Width, FunnelPicture.Height);
e.Graphics.DrawRectangle(Pens.Black, r); e.Handled = true; //e.Paint(e.CellBounds, DataGridViewPaintParts.All);
//e.Graphics.DrawImage(FunnelPicture, (e.CellBounds.Width - FunnelPicture.Width) / 2, (e.CellBounds.Height - FunnelPicture.Height) / 2, FunnelPicture.Width, FunnelPicture.Height);
//e.Handled = true;
} /// <summary>
/// Performs customized column header painting when the popup is visibile.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.Windows.Forms.DataGridViewCellPaintingEventArgs"/> instance containing the event data.</param>
/// <remarks>
/// Override this method to provide your own painting
/// </remarks>
protected virtual void OnHighlightedColumnPaint(object sender, DataGridViewCellPaintingEventArgs e)
{
if (e.ColumnIndex != mCurrentColumnIndex || e.RowIndex != -) return;
e.Paint(e.CellBounds, DataGridViewPaintParts.All);
Rectangle r = new Rectangle(e.CellBounds.X + , e.CellBounds.Y + , e.CellBounds.Width - , e.CellBounds.Height - );
e.Graphics.DrawRectangle(Pens.Yellow, r);
e.Handled = true;
} /// <summary>
/// Performs customized column header painting when the column is filtered.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.Windows.Forms.DataGridViewCellPaintingEventArgs"/> instance containing the event data.</param>
/// <remarks>
/// Override this method to provide your own painting
/// </remarks>
protected virtual void OnFilteredColumnPaint(object sender, DataGridViewCellPaintingEventArgs e)
{
e.Graphics.FillRectangle(Brushes.Orange, e.CellBounds);
e.Paint(e.CellBounds, e.PaintParts & ~DataGridViewPaintParts.Background);
Rectangle r = new Rectangle(e.CellBounds.X + , e.CellBounds.Y + , e.CellBounds.Width - , e.CellBounds.Height - );
e.Graphics.DrawRectangle(Pens.Orange, r);
e.Handled = true; } #endregion #region FILTERHOST MANAGING //Forces column header repaint when popup is closed, cleaning customized painting performed by OnHighlightedColumnPaint
private void Popup_Closed(object sender, ToolStripDropDownClosedEventArgs e)
{
mDataGridView.InvalidateCell(mCurrentColumnIndex, -); // Force header repaint (to hide the selection yellow frame)
} /// <summary>
/// Shows the popup.
/// </summary>
/// <param name="ColumnIndex">Index of the column.</param>
public void ShowPopup(int ColumnIndex)
{
if (mColumnFilterList[ColumnIndex] == null) return; // non-data column
int OldColumnIndex = mCurrentColumnIndex;
mCurrentColumnIndex = ColumnIndex;
Rectangle r = mDataGridView.GetCellDisplayRectangle(ColumnIndex, -, false); // get the header size info
FilterHost.CurrentColumnFilter = mColumnFilterList[ColumnIndex];
try
{
//use "try" because old column could have been removed
mDataGridView.InvalidateCell(OldColumnIndex, -);
}
catch { }
ColumnFilterEventArgs e = new ColumnFilterEventArgs(mDataGridView.Columns[ColumnIndex], mColumnFilterList[ColumnIndex]);
if (PopupShowing != null) PopupShowing(this, e);
if (!e.Handled) FilterHost.Popup.Show(mDataGridView, r.X + r.Width - , r.Y - ); // show the filterhost popup near the column
FilterHost.Popup.Focus(); mDataGridView.InvalidateCell(mCurrentColumnIndex, -); // Force header repaint (to show a selection yellow frame) } #endregion #region COLUMN FILTERS MANAGING /// <summary>
/// Activates / Deactivates the filter for the column specified by ColumnIndex.
/// </summary>
/// <param name="Active">The active state to set</param>
/// <param name="ColumnIndex">Index of the column.</param>
public void ActivateFilter(bool Active, int ColumnIndex)
{
this[ColumnIndex].Active = Active;
RebuildFilter();
} /// <summary>
/// Activates / Deactivates the filter for the column specified by ColumnName.
/// </summary>
/// <param name="Active">The active state to set</param>
/// <param name="ColumnName">Name of the column.</param>
public void ActivateFilter(bool Active, string ColumnName)
{
this[ColumnName].Active = Active;
RebuildFilter();
} /// <summary>
/// Activates / Deactivates the filter for the current, that is last right-clicked, column.
/// </summary>
/// <param name="Active">The active state to set</param>
public void ActivateFilter(bool Active)
{
if (mCurrentColumnIndex == -) return;
this[mCurrentColumnIndex].Active = Active;
if (Active) this[mCurrentColumnIndex].FilterExpressionBuild();
RebuildFilter();
} /// <summary>
/// Activates / Deactivates all filters.
/// </summary>
/// <param name="Active">The active state to set</param>
public void ActivateAllFilters(bool Active)
{
foreach (DgvBaseColumnFilter CF in mColumnFilterList)
{
if (CF == null) continue;
CF.Active = Active;
if (Active) CF.FilterExpressionBuild();
}
RebuildFilter();
} /// <summary>
/// Rebuilds the whole filter expression.
/// </summary>
/// <remarks>
/// The whole filter expression is the conjunction of each <i>column filter</i> and the <see cref="BaseFilter"/>.
/// Call this method to refresh and apply the whole filter expression.
/// </remarks>
public void RebuildFilter()
{
mFilterIsActive = false;
string Filter = "";
foreach (DgvBaseColumnFilter CF in mColumnFilterList)
{
if (CF == null) continue;
if (CF.Active && CF.FilterExpression != "")
{
Filter += " AND (" + CF.FilterExpression + ")";
CF.DataGridViewColumn.HeaderText = CF.FilterCaption;
}
else
{
CF.DataGridViewColumn.HeaderText = CF.OriginalDataGridViewColumnHeaderText;
} }
if (Filter != "")
{
mFilterIsActive = true;
Filter = (mBaseFilter == "") ? "1=1 " + Filter : mBaseFilter + " " + Filter;
}
else
Filter = mBaseFilter; // Apply the filter only if any changes occurred
try
{
if (mBindingSource != null)
{
if (mBindingSource.Filter != Filter) mBindingSource.Filter = Filter;
}
else
{
if (mBoundDataView.RowFilter != Filter) mBoundDataView.RowFilter = Filter;
}
}
catch { Console.WriteLine("Invalid filter: " + Filter); } } #endregion #region HELPERS // Checks if the DataGridView is data bound and the data source finally resolves to a DataView.
private void FindDataView()
{
mBindingSource = null;
object DataSource = mDataGridView.DataSource;
string DataMember = mDataGridView.DataMember; string ExceptionMsg = "DataGridViewFilter can only work with bound DataGridView. The DataSource must be a DataSet, a DataTable, a DataView or a BindingSource which is bound to a DataSet, a DataTable or a DataView "; while (!(DataSource is DataView))
{ if (DataSource == null)
{
return;
} if (DataSource is BindingSource)
{
mBindingSource = (BindingSource)DataSource;
DataMember = ((BindingSource)DataSource).DataMember;
DataSource = ((BindingSource)DataSource).DataSource;
continue;
}
if (DataSource is DataSet)
{
DataSource = ((DataSet)DataSource).Tables[DataMember];
DataMember = "";
continue;
}
if (DataSource is DataTable)
{
DataSource = ((DataTable)DataSource).DefaultView;
break;
}
if (DataSource is IList)
{
var oTable = Fill(DataSource);
DataSource = oTable == null ? new DataView() : oTable.DefaultView;
break;
}
//other types are not allowed
throw new Exception(ExceptionMsg);
}
mBoundDataView = (DataView)DataSource;
} private DataTable Fill(object obj)
{
if (!(obj is IList))
{
return null;
}
var objlist = obj as IList;
if (objlist == null || objlist.Count <= )
{
return null;
}
var tType = objlist[];
DataTable dt = new DataTable(tType.GetType().Name);
DataColumn column;
DataRow row;
System.Reflection.PropertyInfo[] myPropertyInfo = tType.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var t in objlist)
{
if (t == null)
{
continue;
}
row = dt.NewRow();
for (int i = , j = myPropertyInfo.Length; i < j; i++)
{
System.Reflection.PropertyInfo pi = myPropertyInfo[i];
string name = pi.Name;
if (dt.Columns[name] == null)
{
var coltype = pi.PropertyType;
if (coltype.Name == "Nullable`1")
{
//coltype = typeof(System.DBNull);
column = new DataColumn(name);
}
else
{
column = new DataColumn(name, coltype);
}
dt.Columns.Add(column);
}
row[name] = pi.GetValue(t, null);
}
dt.Rows.Add(row);
}
return dt;
} //The funnel picture
private static Image mFilterPicture; /// <summary>
/// Gets a funnel picture.
/// </summary>
public static Image FunnelPicture
{
get
{
if (mFilterPicture == null)
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DgvFilterHost));
mFilterPicture = ((System.Drawing.Image)(resources.GetObject("pictureBox1.Image")));
}
return mFilterPicture;
}
} private void CreateColumnFilter(DataGridViewColumn c)
{
if (mBoundDataView == null) return;
if (!mAutoCreateFilters) return;
//Raise the event about column filter creation
ColumnFilterEventArgs e = new ColumnFilterEventArgs(c, null);
if (ColumnFilterAdding != null) ColumnFilterAdding(this, e);
//if not provided, by an event handler, proceed with standard filter creation
if (e.ColumnFilter == null)
{
Type DataType = null;
if (c.DataPropertyName != "")
{
DataType = mBoundDataView.Table.Columns[c.DataPropertyName].DataType; switch (c.GetType().Name)
{
case "DataGridViewComboBoxColumn":
e.ColumnFilter = new DgvComboBoxColumnFilter();
break;
case "DataGridViewCheckBoxColumn":
e.ColumnFilter = new DgvCheckBoxColumnFilter();
break;
case "DataGridViewTextBoxColumn":
if (DataType == typeof(DateTime))
{
e.ColumnFilter = new DgvDateColumnFilter();
}
else
e.ColumnFilter = new DgvTextBoxColumnFilter();
break;
}
}
}
mColumnFilterList[c.Index] = e.ColumnFilter;
if (e.ColumnFilter != null)
{ // == null when non-data column
if (ColumnFilterAdded != null) ColumnFilterAdded(this, e);
e.ColumnFilter.Init(this, FilterHost, c, mBoundDataView);
}
} #endregion }
}

2、DgvBaseFilterHost这个用户控件作为弹出过滤框的基类,代码如下:

public class DgvBaseFilterHost : UserControl {

        #region EVENTS

        /// <summary>
/// Occurs when the current visible <i>column filter</i> is changed.
/// </summary>
public event EventHandler CurrentColumnFilterChanged; #endregion #region PRIVATE FIELDS private ToolStripDropDown mPopup;
private DgvFilterManager mFilterManager;
private DgvBaseColumnFilter mCurrentColumnFilter = null;
private Size mSizeDifference; #endregion #region PROPERTIES /// <summary>
/// Return the effective area to which <i>column filters</i> will be added.
/// </summary>
public virtual Control FilterClientArea { get { return this; } } public virtual ComboBox ComboBoxColumns { get; set; } public virtual Panel PanelFilterText { set; get; } /// <summary>
/// Gets the <b>ToolStripDropDown</b> object used to popup the <i>filter host</i>
/// </summary>
public ToolStripDropDown Popup
{
get {
if (mPopup==null) {
mPopup = new ToolStripDropDown();
ToolStripControlHost ControlHost = new ToolStripControlHost(this);
ControlHost.Padding = Padding.Empty;
ControlHost.Margin = Padding.Empty;
ControlHost.AutoSize = false;
mPopup.Padding = Padding.Empty;
mPopup.Items.Add(ControlHost);
mPopup.Region = this.Region;
}
return mPopup;
}
} /// <summary>
/// Gets or sets the <i>filter manger</i>
/// </summary>
public DgvFilterManager FilterManager {
set { mFilterManager = value; }
get { return mFilterManager; }
} /// <summary>
/// Gets or sets the currently visibile <i>column filter</i> control
/// </summary>
public DgvBaseColumnFilter CurrentColumnFilter {
get { return mCurrentColumnFilter; }
set {
// Called once: store the original size difference of the filterhost and the filterClientArea
if (mSizeDifference == Size.Empty) {
mSizeDifference = System.Drawing.Size.Subtract(this.Size, FilterClientArea.Size);
this.MinimumSize = this.Size;
}
if (mCurrentColumnFilter != null) mCurrentColumnFilter.Visible = false;
mCurrentColumnFilter = value;
DoAutoFit();
if (CurrentColumnFilterChanged != null) {
EventArgs e = new EventArgs();
CurrentColumnFilterChanged(this, e);
}
mCurrentColumnFilter.Visible = true;
}
} /// <summary>
/// Gets the original size difference of the <i>filter host</i> and the <see cref="DgvBaseFilterHost.FilterClientArea"/>.
/// </summary>
public Size SizeDifference {
get { return mSizeDifference; }
} #endregion #region HELPERS /// <summary>
/// Performs growing / shrinking of the <i>filter host</i> to best fit the current visibile <i>column filter</i>.
/// </summary>
/// <remarks>
/// Ovverride this method to provide your own resize logic.
/// </remarks>
protected virtual void DoAutoFit() {
Size NewHostSize = Size.Add(mSizeDifference, mCurrentColumnFilter.Size);
NewHostSize.Width = Math.Max(NewHostSize.Width, this.MinimumSize.Width);
NewHostSize.Height= Math.Max(NewHostSize.Height, this.MinimumSize.Height);
this.Size = NewHostSize; FilterClientArea.Size = Size.Subtract(NewHostSize, mSizeDifference);
AlignFilter();
} /// <summary>
/// Aligns the <i>column filter</i> into the filter client area.
/// </summary>
/// <remarks>
/// Ovverride this method to provide your own alignment logic.
/// </remarks>
protected void AlignFilter() {
int x = ; // VFilterAlignmentType.Left:
int y = ; // HFilterAlignmentType.Top:
switch (mCurrentColumnFilter.VFilterAlignment){
case VFilterAlignment.Right:
x = FilterClientArea.Width - mCurrentColumnFilter.Width;
break;
case VFilterAlignment.Center:
x = (FilterClientArea.Width - mCurrentColumnFilter.Width) / ;
break;
} switch (mCurrentColumnFilter.HFilterAlignment) {
case HFilterAlignment.Bottom:
y = FilterClientArea.Height - mCurrentColumnFilter.Height;
break;
case HFilterAlignment.Middle:
y = (FilterClientArea.Height - mCurrentColumnFilter.Height) / ;
break;
}
//mCurrentColumnFilter.Location = new Point(x, y); mCurrentColumnFilter.Location = new Point(, );
} /// <summary>
/// Returns a region based on the transparency color of a bitmap.
/// </summary>
/// <param name="bitmap">The bitmap.</param>
/// <param name="transparencyColor">The transparency color.</param>
/// <returns>A region</returns>
public static Region BitmapToRegion(Bitmap bitmap, Color transparencyColor) {
if (bitmap == null)
throw new ArgumentNullException("Bitmap", "Bitmap cannot be null!"); int height = bitmap.Height;
int width = bitmap.Width; GraphicsPath path = new GraphicsPath(); for (int j = ; j < height; j++)
for (int i = ; i < width; i++) {
if (bitmap.GetPixel(i, j) == transparencyColor)
continue; int x0 = i; while ((i < width) && (bitmap.GetPixel(i, j) != transparencyColor))
i++; path.AddRectangle(new Rectangle(x0, j, i - x0, ));
} Region region = new Region(path);
path.Dispose();
return region;
} /// <summary>
/// Registers the a combo box.
/// </summary>
/// <param name="comboBox">The combo box.</param>
/// <remarks>
/// When the user clicks on an <b>ComboBox</b> item that is outside of the
/// host area, this cause an unwanted closing of the <i>filter host</i>.
/// If you use a <b>ComboBox</b> in a customized <i>column filter</i>,
/// be sure to call this method in your filter intitialitazion code.
/// </remarks>
public void RegisterComboBox (ComboBox comboBox){
comboBox.DropDown += new EventHandler(onDropDown);
comboBox.DropDownClosed += new EventHandler(onDropDownClosed);
} private void onDropDown(object sender, EventArgs e)
{
//this.Popup.AutoClose = false;
} private void onDropDownClosed(object sender, EventArgs e)
{
//this.Popup.AutoClose = true;
} #endregion }

3、DgvBaseFilterHost的实现类

[ToolboxItem(false)]
public partial class DgvFilterHost : DgvBaseFilterHost { /// <summary>
/// Initializes a new instance of the <see cref="DgvFilterHost"/> class.
/// </summary>
public DgvFilterHost() {
InitializeComponent();
this.CurrentColumnFilterChanged += new EventHandler(DgvFilterHost_CurrentColumnFilterChanged);
//不用点击非弹出框就关闭
this.Popup.AutoClose = false;
} void DgvFilterHost_CurrentColumnFilterChanged(object sender, EventArgs e) {
//lblColumnName.Text = CurrentColumnFilter.OriginalDataGridViewColumnHeaderText;
} /// <summary>
/// Return the effective area to which the <i>column filters</i> will be added.
/// </summary>
/// <value></value>
public override Control FilterClientArea {
get {
return this.panelFilterArea;
}
} public override ComboBox ComboBoxColumns
{
get
{
return this.comboBox_Cols;
}
//set
//{
// this.comboBox_Cols = value;
//}
} public override Panel PanelFilterText
{
get
{
return this.panelFilterText;
}
//set
//{
// this.panelFilterText = value;
//}
} private void tsOK_Click(object sender, EventArgs e) {
//FilterManager.ActivateFilter(true);
FilterManager.RebuildFilter();
//this.Popup.Close();
this.FindForm().Hide();
} private void tsRemove_Click(object sender, EventArgs e) {
FilterManager.ActivateFilter(false);
this.Popup.Close();
} private void tsRemoveAll_Click(object sender, EventArgs e) {
FilterManager.ActivateAllFilters(false);
FilterManager.SetFilterExpression();
//this.Popup.Close();
} private void pictureBox2_Click(object sender, EventArgs e)
{
this.Popup.Close();
} private void pictureBox3_Click(object sender, EventArgs e)
{
//0.激活当前过滤列并过滤
FilterManager.ActivateFilter(true); //1.重新绑定过滤条件
FilterManager.SetFilterExpression();
} }

4、DgvBaseColumnFilter这个用户控件作为过滤列选项的基类,代码如下:

/// <summary>
/// Specifies how the <i>column filter</i> control is horizontally aligned inside the <i>filter host</i>.
/// </summary>
public enum HFilterAlignment { Top, Bottom, Middle } /// <summary>
/// Specifies how the <i>column filter</i> control is vertically aligned inside the <i>filter host</i>.
/// </summary>
public enum VFilterAlignment { Left, Right, Center } /// <summary>
/// The base class from which to derive effective <i>column filter</i> classes
/// </summary>
/// <remarks>
/// The purpose of a <i>column filter</i> control is to contain visual elements allowing the end user to construct a filter.
/// When inheriting from it, you can work just like creating any other user control.
/// This class is a derivation of <b>UserControl</b> and provide functionalities to
/// cooperate with DgvFilterManager.
/// <para>
/// NOTE:
/// This class must be intended as an abstract class. However, declaring it as abstract,
/// would generate errors whitin the designer when designing derived classes.
/// </para>
/// <para>
/// You should override <see cref="DgvBaseColumnFilter.OnFilterExpressionBuilding"/> to provide a filter expression construction
/// logic and to set the values of the <see cref="DgvBaseColumnFilter.FilterExpression"/> and <see cref="DgvBaseColumnFilter.FilterCaption"/> properties.
/// </para>
/// </remarks>
public class DgvBaseColumnFilter : UserControl { #region EVENTS /// <summary>
/// Occurs before the filter expression is about to be built.
/// </summary>
public event CancelEventHandler FilterExpressionBuilding; /// <summary>
/// Occurs when the filter column is about to be initialized.
/// </summary>
public event CancelEventHandler FilterInitializing; #endregion #region PRIVATE FIELDS private VFilterAlignment mVFilterAlignment = VFilterAlignment.Center;
private HFilterAlignment mHFilterAlignment = HFilterAlignment.Middle;
private DgvBaseFilterHost mFilterHost;
private DgvFilterManager mFilterManager;
private DataGridViewColumn mDataGridViewColumn;
private DataView mBoundDataView;
private Type mColumnDataType;
private string mOriginalDataGridViewColumnHeaderText;
private bool mActive;
private bool mFilterApplySoon = true; private string mFilterExpression = "";
private string mFilterCaption = ""; #endregion #region PROPERTIES /// <summary>
/// Gets or sets a value indicating whether filter apply soon after a user performs some changes.
/// </summary>
/// <value><c>true</c> (default) if to apply soon; otherwise, <c>false</c>.</value>
public bool FilterApplySoon {
get { return mFilterApplySoon; }
set { mFilterApplySoon = value; }
} /// <summary>
/// Gets and sets the filter expression.
/// </summary>
/// <remarks>
/// It's the filter expression on the column. Its value is used by the <see cref="DgvFilterManager"/> to build the whole filter expression.
/// In inherited class, set its value in the override of <see cref="DgvBaseColumnFilter.OnFilterExpressionBuilding"/>.
/// The filter expression must follow the rules of the DataView <see cref="System.Data.DataView.RowFilter"/> property.
/// </remarks>
public string FilterExpression {
get { return mFilterExpression; }
set { mFilterExpression = value; }
} /// <summary>
/// Gets and sets the caption to show in the column header when the filter is active.
/// </summary>
/// <remarks>
/// Represents the caption to show in the column header when the filter is active.
/// In inherited class, set its value in the override of <see cref="DgvBaseColumnFilter.OnFilterExpressionBuilding"/>.
/// </remarks>
public string FilterCaption {
get { return ( (mActive && mFilterExpression!="") ? mFilterCaption : mOriginalDataGridViewColumnHeaderText) ; }
set { mFilterCaption = value; }
} /// <summary>
/// Gets or sets a value indicating whether the filter is active.
/// </summary>
/// <value><c>true</c> if active; otherwise, <c>false</c>.</value>
public bool Active {
get { return (mActive); }
set { mActive = value; }
} /// <summary>
/// Specifies how the <i>column filter</i> control is horizontally aligned inside the <i>filter host</i>.
/// </summary>
public HFilterAlignment HFilterAlignment {
get { return mHFilterAlignment; }
set { mHFilterAlignment = value;
}
} /// <summary>
/// Specifies how the <i>column filter</i> control is vertically aligned inside the <i>filter host</i>.
/// </summary>
public VFilterAlignment VFilterAlignment {
get { return mVFilterAlignment; }
set { mVFilterAlignment = value; }
} /// <summary>
/// Gets the <b>DataView</b> acting as the data source of the <b>DataGridView</b> to which this <i>column filter</i> is applied.
/// </summary>
public DataView BoundDataView { get { return mBoundDataView; }} /// <summary>
/// Gets the <i>filter host</i> control in which this <i>column filter</i> is shown.
/// </summary>
public DgvBaseFilterHost FilterHost { get { return mFilterHost; }} /// <summary>
/// Gets the <i>filter manager</i>.
/// </summary>
public DgvFilterManager FilterManager { get { return mFilterManager; }} /// <summary>
/// Gets the <b>DataGridView</b> column to which this <i>column filter</i> is applied.
/// </summary>
/// <value>The data grid view column.</value>
public DataGridViewColumn DataGridViewColumn { get { return mDataGridViewColumn; }} /// <summary>
/// Gets the type of the data bound to the <b>DataGridView</b> column.
/// </summary>
public Type ColumnDataType { get { return mColumnDataType; }} /// <summary>
/// Gets the original <b>DataGridView</b> column header text.
/// </summary>
public string OriginalDataGridViewColumnHeaderText { get { return mOriginalDataGridViewColumnHeaderText; } } #endregion #region FILTER INITIALIZATION, EXPRESSION BUILDING, EVENT MANAGING /// <summary>
/// Called by the <i>filter manager</i>, inits the <i>column filter</i> and raises the FilterInitializing event.
/// </summary>
/// <param name="FilterManager">The <i>filter manager</i>.</param>
/// <param name="FilterHost">The filter host.</param>
/// <param name="gridColumn">The DataGridView column.</param>
/// <param name="boundDataView">The bound data view.</param>
public void Init(DgvFilterManager FilterManager, DgvBaseFilterHost FilterHost, DataGridViewColumn gridColumn,DataView boundDataView){
this.mFilterManager = FilterManager;
this.mFilterHost = FilterHost;
this.mDataGridViewColumn = gridColumn;
this.mBoundDataView = boundDataView;
this.mOriginalDataGridViewColumnHeaderText = gridColumn.HeaderText;
if (gridColumn.DataPropertyName != "")
this.mColumnDataType = boundDataView.Table.Columns[gridColumn.DataPropertyName].DataType;
else
this.mColumnDataType = typeof(string);
FilterHost.FilterClientArea.Controls.Add(this);
FilterHost.Location = new System.Drawing.Point(, );
this.Visible = false;
CancelEventArgs e = new CancelEventArgs(false);
OnFilterInitializing(this, e);
} /// <summary>
/// Raises the <see cref="DgvBaseColumnFilter.FilterInitializing"/> event
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.ComponentModel.CancelEventArgs"/> instance containing the event data.</param>
/// <remarks>
/// When this <i>column filter</i> control is added to the <i>column filters</i> array of the <i>filter manager</i>,
/// the latter calls the <see cref="DgvBaseColumnFilter.Init"/> method which, in turn, calls this method.
/// You can ovverride this method to provide initialization code.
/// </remarks>
protected virtual void OnFilterInitializing(object sender, CancelEventArgs e) {
// Ovverride to add custom init code
if (FilterInitializing != null) FilterInitializing(sender, e);
} /// <summary>
/// Forces the rebuilt of filter expression
/// </summary>
/// <remarks>
/// This method is called by <see cref="DgvFilterManager"/> when popup is closed, to
/// force recreation of the filter expression.
/// </remarks>
public void FilterExpressionBuild() {
CancelEventArgs e = new CancelEventArgs(false);
OnFilterExpressionBuilding(this,e);
} /// <summary>
/// Raises the <see cref="DgvBaseColumnFilter.FilterExpressionBuilding"/> event
/// </summary>
/// <param name="sender">The event source.</param>
/// <param name="e">The <see cref="System.ComponentModel.CancelEventArgs"/> instance containing the event data.</param>
/// <remarks>
/// Override <b>OnFilterExpressionBuilding</b> to provide a filter expression construction
/// logic and to set the values of the <see cref="DgvBaseColumnFilter.FilterExpression"/> and <see cref="DgvBaseColumnFilter.FilterCaption"/> properties.
/// The <see cref="DgvFilterManager"/> will use these properties in constructing the whole filter expression and to change the header text of the filtered column.
/// </remarks>
protected virtual void OnFilterExpressionBuilding(object sender,CancelEventArgs e) {
if (FilterExpressionBuilding != null) FilterExpressionBuilding(sender, e);
} #endregion #region HELPERS /// <summary>
/// Escapes a string to be suitable for filter expression.
/// </summary>
/// <param name="s">The string to escape.</param>
/// <returns>The escaped string</returns>
public static string StringEscape(string s){
char[] sarray = s.ToCharArray();
StringBuilder sb = new StringBuilder(s.Length * );
foreach (char c in sarray) {
switch (c){
case '%': case '*': case '[': case ']':
sb.Append("[" + c + "]");
break;
case '\'':
sb.Append("''");
break;
default:
sb.Append(c);
break;
}
}
return sb.ToString();
} /// <summary>
/// Returns the string representation of the passed value, based on target type.
/// </summary>
/// <param name="value">The value to be formatted.</param>
/// <param name="targetType">The target type.</param>
/// <returns>The string representation of the passed value</returns>
public static string FormatValue(object value,Type targetType){
if (targetType == typeof(string)) return "'" + value.ToString() + "'";
try {
value = Convert.ChangeType(value, targetType);
} catch { return ""; } if (targetType == typeof(bool)) return ((bool)value) ? "" : "";
if (targetType == typeof(DateTime)) return "'" + ((DateTime)value).ToString("yyyy'-'MM'-'dd") +"'";
//Numeric types
return ((IFormattable)value).ToString(null, NumberFormatInfo.InvariantInfo);
} /// <summary>
/// Returns a null condition string to be used in filter expression.
/// </summary>
/// <param name="DataColumnName">Name of the data column.</param>
/// <returns>A string to be used in the filter expression representing a null condition</returns>
public static string GetNullCondition (string DataColumnName){
return "ISNULL(CONVERT(" + DataColumnName+ ",'System.String'),'NULLVALUE') = 'NULLVALUE'";
} /// <summary>
/// Returns a not null condition string to be used in filter expression.
/// </summary>
/// <param name="DataColumnName">Name of the data column.</param>
/// <returns>A string to be used in the filter expression representing a not null condition</returns>
public static string GetNotNullCondition (string DataColumnName){
return "ISNULL(CONVERT(" + DataColumnName+ ",'System.String'),'NULLVALUE') <> 'NULLVALUE'";
} #endregion }

5、DgvBaseColumnFilter的实现类有多个,分别定义不同类型的过滤列:

5.1、Textbox原型的过滤子类

5.2、ComboBox原型的过滤子类

应博友要求,附上源码。源码下载

源码可能和贴图上面不太一样,是因为贴图上面是和我们项目样式相关的,项目太大,无法贴上来。源码是测试功能用的,原来从别处下载下来改写了下,但功能和贴图上面是差不多的,有兴趣的可以看看。

Winform系列——好用的DataGridview过滤控件(表格的高级搜索功能)的更多相关文章

  1. [工作札记]03: 微软Winform窗体中ListView、DataGridView等控件的Bug,会导致程序编译失败,影响范围:到最新的.net4.7.2都有

    工作中,我们发现了微软.net WinForm的一个Bug,会导致窗体设计器自动生成的代码失效,这个Bug从.net4.5到最新的.net4.7.2都存在,一直没有解决.最初是我在教学工作中发现的,后 ...

  2. WinForm中获取Listbox、DataGridView等控件某行对应的数据

    Listbox:listbox.SelectedItem as XXX DataGridView:dataGridView1.Rows[i].Cells[1].Value.ToString()

  3. WinForm控件复杂数据绑定常用数据源(对Combobox,DataGridView等控件DataSource赋值的多种方法)

    开始以前,先认识一下WinForm控件数据绑定的两种形式,简单数据绑定和复杂数据绑定. 1) 简单数据绑定 简单的数据绑定是将用户控件的某一个属性绑定至某一个类型实例上的某一属性.采用如下形式进行绑定 ...

  4. Winform控件之DataGridView数据控件显示问题

    近期在做同类的信息记录管理系统时遇到了DataGridView数据控件的显示问题.可能是2015年的上半年没有深入 学习C#开发的原因.这几天又一次搬出来开发,首先遇到的问题就是动态绑定数据显示的问题 ...

  5. Atitit..组件化事件化的编程模型--(2)---------Web datagridview 服务器端控件的实现原理and总结

    Atitit..组件化事件化的编程模型--(2)---------Web datagridview 服务器端控件的实现原理and总结 1. 服务端table控件的几个流程周期 1 1.1. 确认要显示 ...

  6. WPF加载Winform窗体时 报错:子控件不能为顶级窗体

    一.wpf项目中引用WindowsFormsIntegration和System.Windows.Forms 二.Form1.Designer.cs 的 partial class Form1 设置为 ...

  7. 一步一步学Silverlight 2系列(9):使用控件模板

    述 Silverlight 2 Beta 1版本发布了,无论从Runtime还是Tools都给我们带来了很多的惊喜,如支持框架语言Visual Basic, Visual C#, IronRuby, ...

  8. C#使用FileSystemWatcher控件实现的文件监控功能示例

    本文实例讲述了C#使用FileSystemWatcher控件实现的文件监控功能.分享给大家供大家参考,具体如下: FileSystemWatcher 可以使用FileSystemWatcher组件监视 ...

  9. Web控件文本框Reset的功能

    在前一篇中<怎样实现Web控件文本框Reset的功能>http://www.cnblogs.com/insus/p/4120889.html Insus.NET只实现了文本框的功能.单个或 ...

随机推荐

  1. Excel列A、B、C、D----与列序号的转换

    public static class ExcelConvert { public static int ToExcelIndex(this string columnName) { if (!Reg ...

  2. springboot 通过 tomcat 部署的配置

    spring-boot 有一个主类,是可以直接 run,然后就可以访问了,但是如果我们想像传统的那种 web 项目一样部署在 tomcat 里,要怎么配置呢.我们一起来看下. pom.xml 里添加如 ...

  3. some knowledge of the IT world

    IT世界一切皆是可信息化(数据的转换)即信息记录一切,对信息的控制{存储,运算,传输{信息的位置转移},转换}就是对一切的控制{硬件(实质维)以信息的控制{软件形式(存在维)}进行操作} 信息本身的实 ...

  4. repo 用法

    repo的用法(zz) 注:repo只是google用Python脚本写的调用git的一个脚本,主要是用来下载.管理Android项目的软件仓库.(也就是说,他是用来管理给git管理的一个个仓库的) ...

  5. 调用接口,发送https请求

    调用https接口有两种方式 一:是导入证书; 证书调用https请求本人还不知道,希望看见此博客的大神给我回复. 二:是创建信任管理器. 第一步:实现X509TrustManager接口,里面的方法 ...

  6. Java基础知识提要

    1. 简述Java的基本历史 java起源于SUN公司的一个GREEN的项目,其原先目的是:为家用消费电子产品发送一个信息的分布式代码系统,通过发送信息控制电视机.冰箱等   2. 简单写出Java特 ...

  7. 一次java Cpu占用过高的排查

    某一个项目CPU占用率一直很高,经常在40%-50%之间,最近比较闲,就开始了排查工作. 1.通过 jstack命令输出进程的堆栈信息 jstack 2788 >C:\log.txt 将堆栈信息 ...

  8. 16bit CRC算法C语言实现

    #define CRC_16_POLYNOMIALS 0x8005 unsigned short CRC16_3(unsigned char* pchMsg, unsigned short wData ...

  9. Python学习笔记【第六篇】:迭代器、生成器、高阶函数、装饰器

    迭代器 迭代器是访问集合元素的一种方式,迭代器从对象的第一个元素开始访问,知道所有元素被访问完成.迭代器只能往前访问,不能通过索引访问. 类型内部使用__iter__()方法转为迭代器,使用__nex ...

  10. 《http权威指南》读书笔记16

    概述 最近对http很感兴趣,于是开始看<http权威指南>.别人都说这本书有点老了,而且内容太多.我个人觉得这本书写的太好了,非常长知识,让你知道关于http的很多概念,不仅告诉你怎么做 ...