• 热门专题

Winform系列好用的DataGridview过滤控件(表格的高级搜索功能)

作者:懒得安分  发布日期:2015-06-29 20:55:22
Tag标签:好用  控件  表格  
  •      上一篇  Winform系列——好看的DataGridView折叠控件 中主要介绍了DataGridview的表格多级折叠功能。这章主要介绍下最近封装的另一个DataGridview表格高级过滤的功能。此功能也是参照codeproject上面的源码改写的,代码可能有源码的内容,也有本人改写过的,所以看上去可能有点乱。废话不多说,上图:

     1、一般的DataGridview效果:

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

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

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

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

       

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

    1、向外暴露的使用类:这个类主穴ky"http://www.it165.net/qq/" target="_blank" class="keylink">qq5psTcysfNqLn9ubnU7Lqvyv0mbmJzcDtwdWJsaWMgRGd2RmlsdGVyTWFuYWdlcihEYXRhR3JpZFZpZXcgZGF0YUdyaWRWaWV3LCBib29sIGF1dG9DcmVhdGVGaWx0ZXJzKXt9vatEYXRhR3JpZHZpZXe21M/ztKu9+MC0o6zIu7rz1Nm4+ERhdGFHcmlkdmlld9T2vNPKwrz+us23vbeoyrXP1rXEoaO0+sLryOfPwqO6PC9wPgo8aW1nIGlkPQ=="code_img_closed_d62d23a9-6923-4a56-acff-0de54dae04cb" class="code_img_closed" src="http://www.it165.net/uploadfile/files/2015/0629/20150629192531161.gif" alt="" />

    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,Can				
About IT165 - 广告服务 - 隐私声明 - 版权申明 - 免责条款 - 网站地图 - 网友投稿 - 联系方式
本站内容来自于互联网,仅供用于网络技术学习,学习中请遵循相关法律法规