Winform系列——好用的DataGridview过滤控件(表格的高级搜索功能)
上一篇 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 = -1; // 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 == -1 && e.ColumnIndex > -1) { if (oMenuStrip == null) { oMenuStrip = new ContextMenuStrip(); oMenuStrip.Size = new System.Drawing.Size(395, 100); } 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(213, 22); 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(213, 22); 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, -1, 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[0] }; 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 == -1) 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 == -1) return; SetCurrentFilterIndex(iFilterIndex); } //根据过滤列的名称得到过滤列的列索引 private int GetFilterIndexByFilterName(string strFilterName) { int iRes = -1; var lstCols = mDataGridView.Columns; foreach (DataGridViewColumn oCol in lstCols) { if (oCol.Name == strFilterName ||oCol.HeaderText.Contains(strFilterName)) { if (mColumnFilterList[oCol.Index] == null) return -1; // 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, -1); } 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 = 7; //0.先清空表达式再重新绘制控件 FilterHost.PanelFilterText.Controls.Clear(); var panelFilterText = new EwinPanel(); panelFilterText.AutoScroll = true; panelFilterText.HorizontalScrollbar = true; panelFilterText.HorizontalScrollbarBarColor = true; panelFilterText.HorizontalScrollbarHighlightOnWheel = false; panelFilterText.HorizontalScrollbarSize = 10; panelFilterText.Location = new System.Drawing.Point(2, 2); panelFilterText.Name = "panelFilterText1"; panelFilterText.Size = new System.Drawing.Size(458, 133); panelFilterText.VerticalScrollbar = true; panelFilterText.VerticalScrollbarBarColor = true; panelFilterText.VerticalScrollbarHighlightOnWheel = false; panelFilterText.VerticalScrollbarSize = 10; panelFilterText.ShowBorder = false; foreach (var strText in arrFilterText) { //1.新增panel var oPanelText = new EwinPanel(); oPanelText.Name = "oPanelText" + y; oPanelText.Location = new System.Drawing.Point(1, y); oPanelText.Size = new System.Drawing.Size(445, 25); 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(10, 0); oLabelText.Name = "label_filtertext" + y; oLabelText.Text = strText.Trim().Trim(new char[2] { '(', ')' }); oLabelText.Size = new System.Drawing.Size(oLabelText.Text.Length * 8, 25); //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 + 10, 3); oPicBox.Size = new System.Drawing.Size(20, 20); var otooltip = new System.Windows.Forms.ToolTip(); otooltip.SetToolTip(oPicBox, "删除过滤条件"); oPicBox.Click += oPicBox_Click; oPicBox.Tag = oLabelText.Text.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries)[0]; oPanelText.Controls.Add(oPicBox); oPanelText.Controls.Add(oLabelText); y = y + 30; 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 != -1) return; //skip if it is not the header row //1.绘制e.RowIndex == -1 && e.ColumnIndex == -1处的过滤图标 //Cell Origin if (e.RowIndex == -1 && e.ColumnIndex == -1 && mFilterIsActive) { OnFilteredGridPaint(sender, e); return; } //2.如果过滤框显示,绘制过滤列表头的边框 //if (FilterHost.Popup.Visible) //{ // OnHighlightedColumnPaint(sender, e); //} //3.绘制过滤列表头的样式 if (e.ColumnIndex == -1) 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 + 1, e.CellBounds.Y + 1, e.CellBounds.Width - 3, e.CellBounds.Height - 4); e.Graphics.DrawImage(FunnelPicture, (e.CellBounds.Width - FunnelPicture.Width) / 2, (e.CellBounds.Height - FunnelPicture.Height) / 2, 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 != -1) return; e.Paint(e.CellBounds, DataGridViewPaintParts.All); Rectangle r = new Rectangle(e.CellBounds.X + 1, e.CellBounds.Y + 1, e.CellBounds.Width - 3, e.CellBounds.Height - 4); 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 + 1, e.CellBounds.Y + 1, e.CellBounds.Width - 3, e.CellBounds.Height - 4); 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, -1); // 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, -1, false); // get the header size info FilterHost.CurrentColumnFilter = mColumnFilterList[ColumnIndex]; try { //use "try" because old column could have been removed mDataGridView.InvalidateCell(OldColumnIndex, -1); } 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 - 4, r.Y - 10); // show the filterhost popup near the column FilterHost.Popup.Focus(); mDataGridView.InvalidateCell(mCurrentColumnIndex, -1); // 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 == -1) 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 <= 0) { return null; } var tType = objlist[0]; 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 = 0, 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 = 0; // VFilterAlignmentType.Left: int y = 0; // HFilterAlignmentType.Top: switch (mCurrentColumnFilter.VFilterAlignment){ case VFilterAlignment.Right: x = FilterClientArea.Width - mCurrentColumnFilter.Width; break; case VFilterAlignment.Center: x = (FilterClientArea.Width - mCurrentColumnFilter.Width) / 2; break; } switch (mCurrentColumnFilter.HFilterAlignment) { case HFilterAlignment.Bottom: y = FilterClientArea.Height - mCurrentColumnFilter.Height; break; case HFilterAlignment.Middle: y = (FilterClientArea.Height - mCurrentColumnFilter.Height) / 2; break; } //mCurrentColumnFilter.Location = new Point(x, y); mCurrentColumnFilter.Location = new Point(150, 20); } /// <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 = 0; j < height; j++) for (int i = 0; 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, 1)); } 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(0, 0); 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 * 2); 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) ? "1" : "0"; 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原型的过滤子类
应博友要求,附上源码。源码下载
源码可能和贴图上面不太一样,是因为贴图上面是和我们项目样式相关的,项目太大,无法贴上来。源码是测试功能用的,原来从别处下载下来改写了下,但功能和贴图上面是差不多的,有兴趣的可以看看。