首页 > 技术文章 > c# Winfrom-DataGridView实现筛选功能

billowliu 2016-06-15 15:28 原文

  //应对用户需求,需要在DataGridView中直接进行筛选功能,在网上找了一些代码加上自己修改整理过后的类,仅供参考!
//上面代码可以直接创建类库项目生成DLL文件,下面代码为另外项目引用创建的DLL文件实现的效果.大致效果如下.(做的比较丑~~~~)
   1 using System;
   2 using System.Collections.Generic;
   3 using System.ComponentModel;
   4 using System.Data;
   5 using System.Diagnostics;
   6 using System.Drawing;
   7 using System.Text;
   8 using System.Windows.Forms;
   9 using System.Windows.Forms.VisualStyles;
  10 using System.Collections;
  11 using System.Reflection;
  12 
  13 
  14 namespace DataGridViewAutoFilter
  15 {
  16    
  17     public class DataGridViewAutoFilterColumnHeaderCell : DataGridViewColumnHeaderCell
  18     {
  19         /// <summary>
  20         /// The ListBox used for all drop-down lists. 
  21         /// </summary>
  22         private FilterListBox dropDownListBox = new FilterListBox();
  23 
  24         /// <summary>
  25         /// A list of filters available for the owning column stored as 
  26         /// formatted and unformatted string values. 
  27         /// </summary>
  28         private System.Collections.Specialized.OrderedDictionary filters =
  29             new System.Collections.Specialized.OrderedDictionary();
  30 
  31         /// <summary>
  32         /// The drop-down list filter value currently in effect for the owning column. 
  33         /// </summary>
  34         private String selectedFilterValue = String.Empty;
  35 
  36         /// <summary>
  37         /// The complete filter string currently in effect for the owning column. 
  38         /// </summary>
  39         private String currentColumnFilter = String.Empty;
  40 
  41         /// <summary>
  42         /// Indicates whether the DataGridView is currently filtered by the owning column.  
  43         /// </summary>
  44         private Boolean filtered;
  45 
  46         /// <summary>
  47         /// Initializes a new instance of the DataGridViewColumnHeaderCell 
  48         /// class and sets its property values to the property values of the 
  49         /// specified DataGridViewColumnHeaderCell.
  50         /// </summary>
  51         /// <param name="oldHeaderCell">The DataGridViewColumnHeaderCell to copy property values from.</param>
  52         public DataGridViewAutoFilterColumnHeaderCell(DataGridViewColumnHeaderCell oldHeaderCell)
  53         {
  54             this.ContextMenuStrip = oldHeaderCell.ContextMenuStrip;
  55             this.ErrorText = oldHeaderCell.ErrorText;
  56             this.Tag = oldHeaderCell.Tag;
  57             this.ToolTipText = oldHeaderCell.ToolTipText;
  58             this.Value = oldHeaderCell.Value;
  59             this.ValueType = oldHeaderCell.ValueType;
  60 
  61             // Use HasStyle to avoid creating a new style object
  62             // when the Style property has not previously been set. 
  63             if (oldHeaderCell.HasStyle)
  64             {
  65                 this.Style = oldHeaderCell.Style;
  66             }
  67 
  68             // Copy this type's properties if the old cell is an auto-filter cell. 
  69             // This enables the Clone method to reuse this constructor. 
  70             DataGridViewAutoFilterColumnHeaderCell filterCell =
  71                 oldHeaderCell as DataGridViewAutoFilterColumnHeaderCell;
  72             if (filterCell != null)
  73             {
  74                 this.FilteringEnabled = filterCell.FilteringEnabled;
  75                 this.AutomaticSortingEnabled = filterCell.AutomaticSortingEnabled;
  76                 this.DropDownListBoxMaxLines = filterCell.DropDownListBoxMaxLines;
  77                 this.currentDropDownButtonPaddingOffset =
  78                     filterCell.currentDropDownButtonPaddingOffset;
  79             }
  80         }
  81 
  82         /// <summary>
  83         /// Initializes a new instance of the DataGridViewColumnHeaderCell 
  84         /// class. 
  85         /// </summary>
  86         public DataGridViewAutoFilterColumnHeaderCell()
  87         {
  88         }
  89 
  90         /// <summary>
  91         /// Creates an exact copy of this cell.
  92         /// </summary>
  93         /// <returns>An object that represents the cloned DataGridViewAutoFilterColumnHeaderCell.</returns>
  94         public override object Clone()
  95         {
  96             return new DataGridViewAutoFilterColumnHeaderCell(this);
  97         }
  98 
  99         /// <summary>
 100         /// Called when the value of the DataGridView property changes
 101         /// in order to perform initialization that requires access to the 
 102         /// owning control and column. 
 103         /// </summary>
 104         /// 
 105 
 106         protected override void OnDataGridViewChanged()
 107         {
 108             // Continue only if there is a DataGridView. 
 109             if (this.DataGridView == null)
 110             {
 111                 return;
 112             }
 113 
 114             // Disable sorting and filtering for columns that can't make
 115             // effective use of them. 
 116             if (OwningColumn != null)
 117             {
 118                 if (OwningColumn is DataGridViewImageColumn ||
 119                 (OwningColumn is DataGridViewButtonColumn &&
 120                 ((DataGridViewButtonColumn)OwningColumn).UseColumnTextForButtonValue) ||
 121                 (OwningColumn is DataGridViewLinkColumn &&
 122                 ((DataGridViewLinkColumn)OwningColumn).UseColumnTextForLinkValue))
 123                 {
 124                     AutomaticSortingEnabled = false;
 125                     FilteringEnabled = false;
 126                 }
 127 
 128                 // Ensure that the column SortMode property value is not Automatic.
 129                 // This prevents sorting when the user clicks the drop-down button.
 130                 if (OwningColumn.SortMode == DataGridViewColumnSortMode.Automatic)
 131                 {
 132                     OwningColumn.SortMode = DataGridViewColumnSortMode.Programmatic;
 133                 }
 134             }
 135 
 136             // Confirm that the data source meets requirements. 
 137             VerifyDataSource();
 138 
 139             // Add handlers to DataGridView events. 
 140             HandleDataGridViewEvents();
 141 
 142             // Initialize the drop-down button bounds so that any initial
 143             // column autosizing will accommodate the button width. 
 144             SetDropDownButtonBounds();
 145 
 146             // Call the OnDataGridViewChanged method on the base class to 
 147             // raise the DataGridViewChanged event.
 148             base.OnDataGridViewChanged();
 149         }
 150 
 151         /// <summary>
 152         /// Confirms that the data source, if it has been set, is a BindingSource.
 153         /// </summary>
 154         private void VerifyDataSource()
 155         {
 156             // Continue only if there is a DataGridView and its DataSource has been set.
 157             if (this.DataGridView == null || this.DataGridView.DataSource == null)
 158             {
 159                 return;
 160             }
 161 
 162             // Throw an exception if the data source is not a BindingSource. 
 163             BindingSource data = this.DataGridView.DataSource as BindingSource;
 164             if (data == null)
 165             {
 166                 throw new NotSupportedException(
 167                     "The DataSource property of the containing DataGridView control " +
 168                     "must be set to a BindingSource.");
 169             }
 170         }
 171 
 172         #region DataGridView events: HandleDataGridViewEvents, DataGridView event handlers, ResetDropDown, ResetFilter
 173 
 174         /// <summary>
 175         /// Add handlers to various DataGridView events, primarily to invalidate 
 176         /// the drop-down button bounds, hide the drop-down list, and reset 
 177         /// cached filter values when changes in the DataGridView require it.
 178         /// </summary>
 179         private void HandleDataGridViewEvents()
 180         {
 181             this.DataGridView.Scroll += new ScrollEventHandler(DataGridView_Scroll);
 182             this.DataGridView.ColumnDisplayIndexChanged += new DataGridViewColumnEventHandler(DataGridView_ColumnDisplayIndexChanged);
 183             this.DataGridView.ColumnWidthChanged += new DataGridViewColumnEventHandler(DataGridView_ColumnWidthChanged);
 184             this.DataGridView.ColumnHeadersHeightChanged += new EventHandler(DataGridView_ColumnHeadersHeightChanged);
 185             this.DataGridView.SizeChanged += new EventHandler(DataGridView_SizeChanged);
 186             this.DataGridView.DataSourceChanged += new EventHandler(DataGridView_DataSourceChanged);
 187             this.DataGridView.DataBindingComplete += new DataGridViewBindingCompleteEventHandler(DataGridView_DataBindingComplete);
 188 
 189             // Add a handler for the ColumnSortModeChanged event to prevent the
 190             // column SortMode property from being inadvertently set to Automatic.
 191             this.DataGridView.ColumnSortModeChanged += new DataGridViewColumnEventHandler(DataGridView_ColumnSortModeChanged);
 192         }
 193 
 194         /// <summary>
 195         /// Invalidates the drop-down button bounds when the user scrolls horizontally.
 196         /// </summary>
 197         /// <param name="sender">The object that raised the event.</param>
 198         /// <param name="e">A ScrollEventArgs that contains the event data.</param>
 199         private void DataGridView_Scroll(object sender, ScrollEventArgs e)
 200         {
 201             if (e.ScrollOrientation == ScrollOrientation.HorizontalScroll)
 202             {
 203                 ResetDropDown();
 204             }
 205         }
 206 
 207         /// <summary>
 208         /// Invalidates the drop-down button bounds when the column display index changes.
 209         /// </summary>
 210         /// <param name="sender"></param>
 211         /// <param name="e"></param>
 212         private void DataGridView_ColumnDisplayIndexChanged(object sender, DataGridViewColumnEventArgs e)
 213         {
 214             ResetDropDown();
 215         }
 216 
 217         /// <summary>
 218         /// Invalidates the drop-down button bounds when a column width changes
 219         /// in the DataGridView control. A width change in any column of the 
 220         /// control has the potential to affect the drop-down button location, 
 221         /// depending on the current horizontal scrolling position and whether
 222         /// the changed column is to the left or right of the current column. 
 223         /// It is easier to invalidate the button in all cases. 
 224         /// </summary>
 225         /// <param name="sender">The object that raised the event.</param>
 226         /// <param name="e">A DataGridViewColumnEventArgs that contains the event data.</param>
 227         private void DataGridView_ColumnWidthChanged(object sender, DataGridViewColumnEventArgs e)
 228         {
 229             ResetDropDown();
 230         }
 231 
 232         /// <summary>
 233         /// Invalidates the drop-down button bounds when the height of the column headers changes.
 234         /// </summary>
 235         /// <param name="sender">The object that raised the event.</param>
 236         /// <param name="e">An EventArgs that contains the event data.</param>
 237         private void DataGridView_ColumnHeadersHeightChanged(object sender, EventArgs e)
 238         {
 239             ResetDropDown();
 240         }
 241 
 242         /// <summary>
 243         /// Invalidates the drop-down button bounds when the size of the DataGridView changes.
 244         /// This prevents a painting issue that occurs when the right edge of the control moves 
 245         /// to the right and the control contents have previously been scrolled to the right.
 246         /// </summary>
 247         /// <param name="sender">The object that raised the event.</param>
 248         /// <param name="e">An EventArgs that contains the event data.</param>
 249         private void DataGridView_SizeChanged(object sender, EventArgs e)
 250         {
 251             ResetDropDown();
 252         }
 253 
 254         /// <summary>
 255         /// Invalidates the drop-down button bounds, hides the drop-down 
 256         /// filter list, if it is showing, and resets the cached filter values
 257         /// if the filter has been removed. 
 258         /// </summary>
 259         /// <param name="sender">The object that raised the event.</param>
 260         /// <param name="e">A DataGridViewBindingCompleteEventArgs that contains the event data.</param>
 261         private void DataGridView_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
 262         {
 263             if (e.ListChangedType == ListChangedType.Reset)
 264             {
 265                 ResetDropDown();
 266                 ResetFilter();
 267             }
 268         }
 269 
 270         /// <summary>
 271         /// Verifies that the data source meets requirements, invalidates the 
 272         /// drop-down button bounds, hides the drop-down filter list if it is 
 273         /// showing, and resets the cached filter values if the filter has been removed. 
 274         /// </summary>
 275         /// <param name="sender">The object that raised the event.</param>
 276         /// <param name="e">An EventArgs that contains the event data.</param>
 277         private void DataGridView_DataSourceChanged(object sender, EventArgs e)
 278         {
 279             VerifyDataSource();
 280             ResetDropDown();
 281             ResetFilter();
 282         }
 283 
 284         /// <summary>
 285         /// Invalidates the drop-down button bounds and hides the filter
 286         /// list if it is showing.
 287         /// </summary>
 288         private void ResetDropDown()
 289         {
 290             InvalidateDropDownButtonBounds();
 291             if (dropDownListBoxShowing)
 292             {
 293                 HideDropDownList();
 294             }
 295         }
 296 
 297         /// <summary>
 298         /// Resets the cached filter values if the filter has been removed.
 299         /// </summary>
 300         private void ResetFilter()
 301         {
 302             if (this.DataGridView == null) return;
 303             BindingSource source = this.DataGridView.DataSource as BindingSource;
 304             if (source == null || String.IsNullOrEmpty(source.Filter))
 305             {
 306                 filtered = false;
 307                 selectedFilterValue = "(All)";
 308                 currentColumnFilter = String.Empty;
 309             }
 310         }
 311 
 312         /// <summary>
 313         /// Throws an exception when the column sort mode is changed to Automatic.
 314         /// </summary>
 315         /// <param name="sender">The object that raised the event.</param>
 316         /// <param name="e">A DataGridViewColumnEventArgs that contains the event data.</param>
 317         private void DataGridView_ColumnSortModeChanged(object sender, DataGridViewColumnEventArgs e)
 318         {
 319             if (e.Column == OwningColumn &&
 320                 e.Column.SortMode == DataGridViewColumnSortMode.Automatic)
 321             {
 322                 throw new InvalidOperationException(
 323                     "A SortMode value of Automatic is incompatible with " +
 324                     "the DataGridViewAutoFilterColumnHeaderCell type. " +
 325                     "Use the AutomaticSortingEnabled property instead.");
 326             }
 327         }
 328 
 329         #endregion DataGridView events
 330 
 331         /// <summary>
 332         /// Paints the column header cell, including the drop-down button. 
 333         /// </summary>
 334         /// <param name="graphics">The Graphics used to paint the DataGridViewCell.</param>
 335         /// <param name="clipBounds">A Rectangle that represents the area of the DataGridView that needs to be repainted.</param>
 336         /// <param name="cellBounds">A Rectangle that contains the bounds of the DataGridViewCell that is being painted.</param>
 337         /// <param name="rowIndex">The row index of the cell that is being painted.</param>
 338         /// <param name="cellState">A bitwise combination of DataGridViewElementStates values that specifies the state of the cell.</param>
 339         /// <param name="value">The data of the DataGridViewCell that is being painted.</param>
 340         /// <param name="formattedValue">The formatted data of the DataGridViewCell that is being painted.</param>
 341         /// <param name="errorText">An error message that is associated with the cell.</param>
 342         /// <param name="cellStyle">A DataGridViewCellStyle that contains formatting and style information about the cell.</param>
 343         /// <param name="advancedBorderStyle">A DataGridViewAdvancedBorderStyle that contains border styles for the cell that is being painted.</param>
 344         /// <param name="paintParts">A bitwise combination of the DataGridViewPaintParts values that specifies which parts of the cell need to be painted.</param>
 345         protected override void Paint(
 346             Graphics graphics, Rectangle clipBounds, Rectangle cellBounds,
 347             int rowIndex, DataGridViewElementStates cellState,
 348             object value, object formattedValue, string errorText,
 349             DataGridViewCellStyle cellStyle,
 350             DataGridViewAdvancedBorderStyle advancedBorderStyle,
 351             DataGridViewPaintParts paintParts)
 352         {
 353             // Use the base method to paint the default appearance. 
 354             base.Paint(graphics, clipBounds, cellBounds, rowIndex,
 355                 cellState, value, formattedValue,
 356                 errorText, cellStyle, advancedBorderStyle, paintParts);
 357 
 358             // Continue only if filtering is enabled and ContentBackground is 
 359             // part of the paint request. 
 360             if (!FilteringEnabled ||
 361                 (paintParts & DataGridViewPaintParts.ContentBackground) == 0)
 362             {
 363                 return;
 364             }
 365 
 366             // Retrieve the current button bounds. 
 367             Rectangle buttonBounds = DropDownButtonBounds;
 368 
 369             // Continue only if the buttonBounds is big enough to draw.
 370             if (buttonBounds.Width < 1 || buttonBounds.Height < 1) return;
 371 
 372             // Paint the button manually or using visual styles if visual styles 
 373             // are enabled, using the correct state depending on whether the 
 374             // filter list is showing and whether there is a filter in effect 
 375             // for the current column. 
 376             if (Application.RenderWithVisualStyles)
 377             {
 378                 ComboBoxState state = ComboBoxState.Normal;
 379 
 380                 if (dropDownListBoxShowing)
 381                 {
 382                     state = ComboBoxState.Pressed;
 383                 }
 384                 else if (filtered)
 385                 {
 386                     state = ComboBoxState.Hot;
 387                 }
 388                 ComboBoxRenderer.DrawDropDownButton(
 389                     graphics, buttonBounds, state);
 390             }
 391             else
 392             {
 393                 // Determine the pressed state in order to paint the button 
 394                 // correctly and to offset the down arrow. 
 395                 Int32 pressedOffset = 0;
 396                 PushButtonState state = PushButtonState.Normal;
 397                 if (dropDownListBoxShowing)
 398                 {
 399                     state = PushButtonState.Pressed;
 400                     pressedOffset = 1;
 401                 }
 402                 ButtonRenderer.DrawButton(graphics, buttonBounds, state);
 403 
 404                 // If there is a filter in effect for the column, paint the 
 405                 // down arrow as an unfilled triangle. If there is no filter 
 406                 // in effect, paint the down arrow as a filled triangle.
 407                 if (filtered)
 408                 {
 409                     graphics.DrawPolygon(SystemPens.ControlText, new Point[] {
 410                         new Point(
 411                             buttonBounds.Width / 2 + 
 412                                 buttonBounds.Left - 1 + pressedOffset, 
 413                             buttonBounds.Height * 3 / 4 + 
 414                                 buttonBounds.Top - 1 + pressedOffset),
 415                         new Point(
 416                             buttonBounds.Width / 4 + 
 417                                 buttonBounds.Left + pressedOffset,
 418                             buttonBounds.Height / 2 + 
 419                                 buttonBounds.Top - 1 + pressedOffset),
 420                         new Point(
 421                             buttonBounds.Width * 3 / 4 + 
 422                                 buttonBounds.Left - 1 + pressedOffset,
 423                             buttonBounds.Height / 2 + 
 424                                 buttonBounds.Top - 1 + pressedOffset)
 425                     });
 426                 }
 427                 else
 428                 {
 429                     graphics.FillPolygon(SystemBrushes.ControlText, new Point[] {
 430                         new Point(
 431                             buttonBounds.Width / 2 + 
 432                                 buttonBounds.Left - 1 + pressedOffset, 
 433                             buttonBounds.Height * 3 / 4 + 
 434                                 buttonBounds.Top - 1 + pressedOffset),
 435                         new Point(
 436                             buttonBounds.Width / 4 + 
 437                                 buttonBounds.Left + pressedOffset,
 438                             buttonBounds.Height / 2 + 
 439                                 buttonBounds.Top - 1 + pressedOffset),
 440                         new Point(
 441                             buttonBounds.Width * 3 / 4 + 
 442                                 buttonBounds.Left - 1 + pressedOffset,
 443                             buttonBounds.Height / 2 + 
 444                                 buttonBounds.Top - 1 + pressedOffset)
 445                     });
 446                 }
 447             }
 448 
 449         }
 450 
 451         /// <summary>
 452         /// Handles mouse clicks to the header cell, displaying the 
 453         /// drop-down list or sorting the owning column as appropriate. 
 454         /// </summary>
 455         /// <param name="e">A DataGridViewCellMouseEventArgs that contains the event data.</param>
 456         protected override void OnMouseDown(DataGridViewCellMouseEventArgs e)
 457         {
 458             Debug.Assert(this.DataGridView != null, "DataGridView is null");
 459 
 460             // Continue only if the user did not click the drop-down button 
 461             // while the drop-down list was displayed. This prevents the 
 462             // drop-down list from being redisplayed after being hidden in 
 463             // the LostFocus event handler. 
 464             if (lostFocusOnDropDownButtonClick)
 465             {
 466                 lostFocusOnDropDownButtonClick = false;
 467                 return;
 468             }
 469 
 470             // Retrieve the current size and location of the header cell,
 471             // excluding any portion that is scrolled off screen. 
 472             Rectangle cellBounds = this.DataGridView
 473                 .GetCellDisplayRectangle(e.ColumnIndex, -1, false);
 474 
 475             // Continue only if the column is not manually resizable or the
 476             // mouse coordinates are not within the column resize zone. 
 477             if (this.OwningColumn.Resizable == DataGridViewTriState.True &&
 478                 ((this.DataGridView.RightToLeft == RightToLeft.No &&
 479                 cellBounds.Width - e.X < 6) || e.X < 6))
 480             {
 481                 return;
 482             }
 483 
 484             // Unless RightToLeft is enabled, store the width of the portion
 485             // that is scrolled off screen. 
 486             Int32 scrollingOffset = 0;
 487             if (this.DataGridView.RightToLeft == RightToLeft.No &&
 488                 this.DataGridView.FirstDisplayedScrollingColumnIndex ==
 489                 this.ColumnIndex)
 490             {
 491                 scrollingOffset =
 492                     this.DataGridView.FirstDisplayedScrollingColumnHiddenWidth;
 493             }
 494 
 495             // Show the drop-down list if filtering is enabled and the mouse click occurred
 496             // within the drop-down button bounds. Otherwise, if sorting is enabled and the
 497             // click occurred outside the drop-down button bounds, sort by the owning column. 
 498             // The mouse coordinates are relative to the cell bounds, so the cell location
 499             // and the scrolling offset are needed to determine the client coordinates.
 500             if (FilteringEnabled &&
 501                 DropDownButtonBounds.Contains(
 502                 e.X + cellBounds.Left - scrollingOffset, e.Y + cellBounds.Top))
 503             {
 504                 // If the current cell is in edit mode, commit the edit. 
 505                 if (this.DataGridView.IsCurrentCellInEditMode)
 506                 {
 507                     // Commit and end the cell edit.  
 508                     this.DataGridView.EndEdit();
 509 
 510                     // Commit any change to the underlying data source. 
 511                     BindingSource source =
 512                         this.DataGridView.DataSource as BindingSource;
 513                     if (source != null)
 514                     {
 515                         source.EndEdit();
 516                     }
 517                 }
 518                 ShowDropDownList();
 519             }
 520             else if (AutomaticSortingEnabled &&
 521                 this.DataGridView.SelectionMode !=
 522                 DataGridViewSelectionMode.ColumnHeaderSelect)
 523             {
 524                 SortByColumn();
 525             }
 526 
 527             base.OnMouseDown(e);
 528         }
 529 
 530         /// <summary>
 531         /// Sorts the DataGridView by the current column if AutomaticSortingEnabled is true.
 532         /// </summary>
 533         private void SortByColumn()
 534         {
 535             Debug.Assert(this.DataGridView != null && OwningColumn != null, "DataGridView or OwningColumn is null");
 536 
 537             // Continue only if the data source supports sorting. 
 538             IBindingList sortList = this.DataGridView.DataSource as IBindingList;
 539             if (sortList == null ||
 540                 !sortList.SupportsSorting ||
 541                 !AutomaticSortingEnabled)
 542             {
 543                 return;
 544             }
 545 
 546             // Determine the sort direction and sort by the owning column. 
 547             ListSortDirection direction = ListSortDirection.Ascending;
 548             if (this.DataGridView.SortedColumn == OwningColumn &&
 549                 this.DataGridView.SortOrder == SortOrder.Ascending)
 550             {
 551                 direction = ListSortDirection.Descending;
 552             }
 553             this.DataGridView.Sort(OwningColumn, direction);
 554         }
 555 
 556         #region drop-down list: Show/HideDropDownListBox, SetDropDownListBoxBounds, DropDownListBoxMaxHeightInternal
 557 
 558         /// <summary>
 559         /// Indicates whether dropDownListBox is currently displayed 
 560         /// for this header cell. 
 561         /// </summary>
 562         private bool dropDownListBoxShowing;
 563 
 564         /// <summary>
 565         /// Displays the drop-down filter list. 
 566         /// </summary>
 567         public void ShowDropDownList()
 568         {
 569             Debug.Assert(this.DataGridView != null, "DataGridView is null");
 570 
 571             // Ensure that the current row is not the row for new records.
 572             // This prevents the new row from affecting the filter list and also
 573             // prevents the new row from being added when the filter changes.
 574             if (this.DataGridView.CurrentRow != null &&
 575                 this.DataGridView.CurrentRow.IsNewRow)
 576             {
 577                 this.DataGridView.CurrentCell = null;
 578             }
 579 
 580             // Populate the filters dictionary, then copy the filter values 
 581             // from the filters.Keys collection into the ListBox.Items collection, 
 582             // selecting the current filter if there is one in effect. 
 583             PopulateFilters();
 584 
 585             String[] filterArray = new String[filters.Count];
 586             filters.Keys.CopyTo(filterArray, 0);
 587             dropDownListBox.Items.Clear();
 588             dropDownListBox.Items.AddRange(filterArray);
 589             dropDownListBox.SelectedItem = selectedFilterValue;
 590 
 591             // Add handlers to dropDownListBox events. 
 592             HandleDropDownListBoxEvents();
 593 
 594             // Set the size and location of dropDownListBox, then display it. 
 595             SetDropDownListBoxBounds();
 596             dropDownListBox.Visible = true;
 597             dropDownListBoxShowing = true;
 598 
 599             Debug.Assert(dropDownListBox.Parent == null,
 600                 "ShowDropDownListBox has been called multiple times before HideDropDownListBox");
 601 
 602             // Add dropDownListBox to the DataGridView. 
 603             this.DataGridView.Controls.Add(dropDownListBox);
 604 
 605             // Set the input focus to dropDownListBox. 
 606             dropDownListBox.Focus();
 607 
 608             // Invalidate the cell so that the drop-down button will repaint
 609             // in the pressed state. 
 610             this.DataGridView.InvalidateCell(this);
 611         }
 612 
 613         /// <summary>
 614         /// Hides the drop-down filter list. 
 615         /// </summary>
 616         public void HideDropDownList()
 617         {
 618             if (DataGridView != null)
 619             {
 620                 Debug.Assert(this.DataGridView != null, "DataGridView is null");
 621 
 622                 // Hide dropDownListBox, remove handlers from its events, and remove 
 623                 // it from the DataGridView control. 
 624                 dropDownListBoxShowing = false;
 625                 dropDownListBox.Visible = false;
 626                 UnhandleDropDownListBoxEvents();
 627                 this.DataGridView.Controls.Remove(dropDownListBox);
 628 
 629                 // Invalidate the cell so that the drop-down button will repaint
 630                 // in the unpressed state. 
 631                 this.DataGridView.InvalidateCell(this);
 632             }
 633         }
 634 
 635         /// <summary>
 636         /// Sets the dropDownListBox size and position based on the formatted 
 637         /// values in the filters dictionary and the position of the drop-down 
 638         /// button. Called only by ShowDropDownListBox.  
 639         /// </summary>
 640         private void SetDropDownListBoxBounds()
 641         {
 642             Debug.Assert(filters.Count > 0, "filters.Count <= 0");
 643 
 644             // Declare variables that will be used in the calculation, 
 645             // initializing dropDownListBoxHeight to account for the 
 646             // ListBox borders.
 647             Int32 dropDownListBoxHeight = 2;
 648             Int32 currentWidth = 0;
 649             Int32 dropDownListBoxWidth = 0;
 650             Int32 dropDownListBoxLeft = 0;
 651 
 652             // For each formatted value in the filters dictionary Keys collection,
 653             // add its height to dropDownListBoxHeight and, if it is wider than 
 654             // all previous values, set dropDownListBoxWidth to its width.
 655             using (Graphics graphics = dropDownListBox.CreateGraphics())
 656             {
 657                 foreach (String filter in filters.Keys)
 658                 {
 659                     SizeF stringSizeF = graphics.MeasureString(
 660                         filter, dropDownListBox.Font);
 661                     dropDownListBoxHeight += (Int32)stringSizeF.Height;
 662                     currentWidth = (Int32)stringSizeF.Width;
 663                     if (dropDownListBoxWidth < currentWidth)
 664                     {
 665                         dropDownListBoxWidth = currentWidth;
 666                     }
 667                 }
 668             }
 669 
 670             // Increase the width to allow for horizontal margins and borders. 
 671             dropDownListBoxWidth += 6;
 672 
 673             // Constrain the dropDownListBox height to the 
 674             // DropDownListBoxMaxHeightInternal value, which is based on 
 675             // the DropDownListBoxMaxLines property value but constrained by
 676             // the maximum height available in the DataGridView control.
 677             if (dropDownListBoxHeight > DropDownListBoxMaxHeightInternal)
 678             {
 679                 dropDownListBoxHeight = DropDownListBoxMaxHeightInternal;
 680 
 681                 // If the preferred height is greater than the available height,
 682                 // adjust the width to accommodate the vertical scroll bar. 
 683                 dropDownListBoxWidth += SystemInformation.VerticalScrollBarWidth;
 684             }
 685 
 686             // Calculate the ideal location of the left edge of dropDownListBox 
 687             // based on the location of the drop-down button and taking the 
 688             // RightToLeft property value into consideration. 
 689             if (this.DataGridView.RightToLeft == RightToLeft.No)
 690             {
 691                 dropDownListBoxLeft = DropDownButtonBounds.Right -
 692                     dropDownListBoxWidth + 1;
 693             }
 694             else
 695             {
 696                 dropDownListBoxLeft = DropDownButtonBounds.Left - 1;
 697             }
 698 
 699             // Determine the left and right edges of the available horizontal
 700             // width of the DataGridView control. 
 701             Int32 clientLeft = 1;
 702             Int32 clientRight = this.DataGridView.ClientRectangle.Right;
 703             if (this.DataGridView.DisplayedRowCount(false) <
 704                 this.DataGridView.RowCount)
 705             {
 706                 if (this.DataGridView.RightToLeft == RightToLeft.Yes)
 707                 {
 708                     clientLeft += SystemInformation.VerticalScrollBarWidth;
 709                 }
 710                 else
 711                 {
 712                     clientRight -= SystemInformation.VerticalScrollBarWidth;
 713                 }
 714             }
 715 
 716             // Adjust the dropDownListBox location and/or width if it would
 717             // otherwise overlap the left or right edge of the DataGridView.
 718             if (dropDownListBoxLeft < clientLeft)
 719             {
 720                 dropDownListBoxLeft = clientLeft;
 721             }
 722             Int32 dropDownListBoxRight =
 723                 dropDownListBoxLeft + dropDownListBoxWidth + 1;
 724             if (dropDownListBoxRight > clientRight)
 725             {
 726                 if (dropDownListBoxLeft == clientLeft)
 727                 {
 728                     dropDownListBoxWidth -=
 729                         dropDownListBoxRight - clientRight;
 730                 }
 731                 else
 732                 {
 733                     dropDownListBoxLeft -=
 734                         dropDownListBoxRight - clientRight;
 735                     if (dropDownListBoxLeft < clientLeft)
 736                     {
 737                         dropDownListBoxWidth -= clientLeft - dropDownListBoxLeft;
 738                         dropDownListBoxLeft = clientLeft;
 739                     }
 740                 }
 741             }
 742 
 743             // Set the ListBox.Bounds property using the calculated values. 
 744             dropDownListBox.Bounds = new Rectangle(dropDownListBoxLeft,
 745                 DropDownButtonBounds.Bottom, // top of drop-down list box
 746                 dropDownListBoxWidth, dropDownListBoxHeight);
 747         }
 748 
 749         /// <summary>
 750         /// Gets the actual maximum height of the drop-down list, in pixels.
 751         /// The maximum height is calculated from the DropDownListBoxMaxLines 
 752         /// property value, but is limited to the available height of the 
 753         /// DataGridView control. 
 754         /// </summary>
 755         protected Int32 DropDownListBoxMaxHeightInternal
 756         {
 757             get
 758             {
 759                 // Calculate the height of the available client area
 760                 // in the DataGridView control, taking the horizontal
 761                 // scroll bar into consideration and leaving room
 762                 // for the ListBox bottom border. 
 763                 Int32 dataGridViewMaxHeight = this.DataGridView.Height -
 764                     this.DataGridView.ColumnHeadersHeight - 1;
 765                 if (this.DataGridView.DisplayedColumnCount(false) <
 766                     this.DataGridView.ColumnCount)
 767                 {
 768                     dataGridViewMaxHeight -=
 769                         SystemInformation.HorizontalScrollBarHeight;
 770                 }
 771 
 772                 // Calculate the height of the list box, using the combined 
 773                 // height of all items plus 2 for the top and bottom border. 
 774                 Int32 listMaxHeight = dropDownListBoxMaxLinesValue * dropDownListBox.ItemHeight + 2;
 775 
 776                 // Return the smaller of the two values. 
 777                 if (listMaxHeight < dataGridViewMaxHeight)
 778                 {
 779                     return listMaxHeight;
 780                 }
 781                 else
 782                 {
 783                     return dataGridViewMaxHeight;
 784                 }
 785             }
 786         }
 787 
 788         #endregion drop-down list
 789 
 790         #region ListBox events: HandleDropDownListBoxEvents, UnhandleDropDownListBoxEvents, ListBox event handlers
 791 
 792         /// <summary>
 793         /// Adds handlers to ListBox events for handling mouse
 794         /// and keyboard input.
 795         /// </summary>
 796         private void HandleDropDownListBoxEvents()
 797         {
 798             dropDownListBox.MouseClick += new MouseEventHandler(DropDownListBox_MouseClick);
 799             dropDownListBox.LostFocus += new EventHandler(DropDownListBox_LostFocus);
 800             dropDownListBox.KeyDown += new KeyEventHandler(DropDownListBox_KeyDown);
 801         }
 802 
 803         /// <summary>
 804         /// Removes the ListBox event handlers. 
 805         /// </summary>
 806         private void UnhandleDropDownListBoxEvents()
 807         {
 808             dropDownListBox.MouseClick -= new MouseEventHandler(DropDownListBox_MouseClick);
 809             dropDownListBox.LostFocus -= new EventHandler(DropDownListBox_LostFocus);
 810             dropDownListBox.KeyDown -= new KeyEventHandler(DropDownListBox_KeyDown);
 811         }
 812 
 813         /// <summary>
 814         /// Adjusts the filter in response to a user selection from the drop-down list. 
 815         /// </summary>
 816         /// <param name="sender">The object that raised the event.</param>
 817         /// <param name="e">A MouseEventArgs that contains the event data.</param>
 818         private void DropDownListBox_MouseClick(object sender, MouseEventArgs e)
 819         {
 820             Debug.Assert(this.DataGridView != null, "DataGridView is null");
 821 
 822             // Continue only if the mouse click was in the content area
 823             // and not on the scroll bar. 
 824             if (!dropDownListBox.DisplayRectangle.Contains(e.X, e.Y))
 825             {
 826                 return;
 827             }
 828 
 829             UpdateFilter();
 830             HideDropDownList();
 831         }
 832 
 833         /// <summary>
 834         /// Indicates whether the drop-down list lost focus because the
 835         /// user clicked the drop-down button. 
 836         /// </summary>
 837         private Boolean lostFocusOnDropDownButtonClick;
 838 
 839         /// <summary>
 840         /// Hides the drop-down list when it loses focus. 
 841         /// </summary>
 842         /// <param name="sender">The object that raised the event.</param>
 843         /// <param name="e">An EventArgs that contains the event data.</param>
 844         private void DropDownListBox_LostFocus(object sender, EventArgs e)
 845         {
 846             // If the focus was lost because the user clicked the drop-down
 847             // button, store a value that prevents the subsequent OnMouseDown
 848             // call from displaying the drop-down list again. 
 849             if (DropDownButtonBounds.Contains(
 850                 this.DataGridView.PointToClient(new Point(
 851                 Control.MousePosition.X, Control.MousePosition.Y))))
 852             {
 853                 lostFocusOnDropDownButtonClick = true;
 854             }
 855             HideDropDownList();
 856         }
 857 
 858         /// <summary>
 859         /// Handles the ENTER and ESC keys.
 860         /// </summary>
 861         /// <param name="sender">The object that raised the event.</param>
 862         /// <param name="e">A KeyEventArgs that contains the event data.</param>
 863         void DropDownListBox_KeyDown(object sender, KeyEventArgs e)
 864         {
 865             switch (e.KeyCode)
 866             {
 867                 case Keys.Enter:
 868                     UpdateFilter();
 869                     HideDropDownList();
 870                     break;
 871                 case Keys.Escape:
 872                     HideDropDownList();
 873                     break;
 874             }
 875         }
 876 
 877         #endregion ListBox events
 878 
 879         #region filtering: PopulateFilters, FilterWithoutCurrentColumn, UpdateFilter, RemoveFilter, AvoidNewRowWhenFiltering, GetFilterStatus
 880 
 881         /// <summary>
 882         /// Populates the filters dictionary with formatted and unformatted string
 883         /// representations of each unique value in the column, accounting for all 
 884         /// filters except the current column's. Also adds special filter options. 
 885         /// </summary>
 886         private void PopulateFilters()
 887         {
 888             // Continue only if there is a DataGridView.
 889             if (this.DataGridView == null)
 890             {
 891                 return;
 892             }
 893 
 894             // Cast the data source to a BindingSource. 
 895             BindingSource data = this.DataGridView.DataSource as BindingSource;
 896 
 897             Debug.Assert(data != null && data.SupportsFiltering && OwningColumn != null,
 898                 "DataSource is not a BindingSource, or does not support filtering, or OwningColumn is null");
 899 
 900             // Prevent the data source from notifying the DataGridView of changes. 
 901             data.RaiseListChangedEvents = false;
 902 
 903             // Cache the current BindingSource.Filter value and then change 
 904             // the Filter property to temporarily remove any filter for the 
 905             // current column. 
 906             String oldFilter = data.Filter;
 907             data.Filter = FilterWithoutCurrentColumn(oldFilter);
 908 
 909             // Reset the filters dictionary and initialize some flags
 910             // to track whether special filter options are needed. 
 911             filters.Clear();
 912             Boolean containsBlanks = false;
 913             Boolean containsNonBlanks = false;
 914 
 915             // Initialize an ArrayList to store the values in their original
 916             // types. This enables the values to be sorted appropriately.  
 917             ArrayList list = new ArrayList(data.Count);
 918 
 919             // Retrieve each value and add it to the ArrayList if it isn't
 920             // already present. 
 921             foreach (Object item in data)
 922             {
 923                 Object value = null;
 924 
 925                 // Use the ICustomTypeDescriptor interface to retrieve properties
 926                 // if it is available; otherwise, use reflection. The 
 927                 // ICustomTypeDescriptor interface is useful to customize 
 928                 // which values are exposed as properties. For example, the 
 929                 // DataRowView class implements ICustomTypeDescriptor to expose 
 930                 // cell values as property values.                
 931                 // 
 932                 // Iterate through the property names to find a case-insensitive
 933                 // match with the DataGridViewColumn.DataPropertyName value.
 934                 // This is necessary because DataPropertyName is case-
 935                 // insensitive, but the GetProperties and GetProperty methods
 936                 // used below are case-sensitive.
 937                 ICustomTypeDescriptor ictd = item as ICustomTypeDescriptor;
 938                 if (ictd != null)
 939                 {
 940                     PropertyDescriptorCollection properties = ictd.GetProperties();
 941                     foreach (PropertyDescriptor property in properties)
 942                     {
 943                         if (String.Compare(this.OwningColumn.DataPropertyName,
 944                             property.Name, true /*case insensitive*/,
 945                             System.Globalization.CultureInfo.InvariantCulture) == 0)
 946                         {
 947                             value = property.GetValue(item);
 948                             break;
 949                         }
 950                     }
 951                 }
 952                 else
 953                 {
 954                     PropertyInfo[] properties = item.GetType().GetProperties(
 955                         BindingFlags.Public | BindingFlags.Instance);
 956                     foreach (PropertyInfo property in properties)
 957                     {
 958                         if (String.Compare(this.OwningColumn.DataPropertyName,
 959                             property.Name, true /*case insensitive*/,
 960                             System.Globalization.CultureInfo.InvariantCulture) == 0)
 961                         {
 962                             value = property.GetValue(item, null /*property index*/);
 963                             break;
 964                         }
 965                     }
 966                 }
 967 
 968                 // Skip empty values, but note that they are present. 
 969                 if (value == null || value == DBNull.Value)
 970                 {
 971                     containsBlanks = true;
 972                     continue;
 973                 }
 974 
 975                 // Add values to the ArrayList if they are not already there.
 976                 if (!list.Contains(value))
 977                 {
 978                     list.Add(value);
 979                 }
 980             }
 981 
 982             // Sort the ArrayList. The default Sort method uses the IComparable 
 983             // implementation of the stored values so that string, numeric, and 
 984             // date values will all be sorted correctly. 
 985             list.Sort();
 986 
 987             // Convert each value in the ArrayList to its formatted representation
 988             // and store both the formatted and unformatted string representations
 989             // in the filters dictionary. 
 990             foreach (Object value in list)
 991             {
 992                 // Use the cell's GetFormattedValue method with the column's
 993                 // InheritedStyle property so that the dropDownListBox format
 994                 // will match the display format used for the column's cells. 
 995                 String formattedValue = null;
 996                 DataGridViewCellStyle style = OwningColumn.InheritedStyle;
 997                 formattedValue = (String)GetFormattedValue(value, -1, ref style,
 998                     null, null, DataGridViewDataErrorContexts.Formatting);
 999 
1000                 if (String.IsNullOrEmpty(formattedValue))
1001                 {
1002                     // Skip empty values, but note that they are present.
1003                     containsBlanks = true;
1004                 }
1005                 else if (!filters.Contains(formattedValue))
1006                 {
1007                     // Note whether non-empty values are present. 
1008                     containsNonBlanks = true;
1009 
1010                     // For all non-empty values, add the formatted and 
1011                     // unformatted string representations to the filters 
1012                     // dictionary.
1013                     filters.Add(formattedValue, value.ToString());
1014                 }
1015             }
1016 
1017             // Restore the filter to the cached filter string and 
1018             // re-enable data source change notifications. 
1019             if (oldFilter != null) data.Filter = oldFilter;
1020             data.RaiseListChangedEvents = true;
1021 
1022             // Add special filter options to the filters dictionary
1023             // along with null values, since unformatted representations
1024             // are not needed. 
1025             filters.Insert(0, "(All)", null);
1026             if (containsBlanks && containsNonBlanks)
1027             {
1028                 filters.Add("(Blanks)", null);
1029                 filters.Add("(NonBlanks)", null);
1030             }
1031         }
1032 
1033         /// <summary>
1034         /// Returns a copy of the specified filter string after removing the part that filters the current column, if present. 
1035         /// </summary>
1036         /// <param name="filter">The filter string to parse.</param>
1037         /// <returns>A copy of the specified filter string without the current column's filter.</returns>
1038         private String FilterWithoutCurrentColumn(String filter)
1039         {
1040             // If there is no filter in effect, return String.Empty. 
1041             if (String.IsNullOrEmpty(filter))
1042             {
1043                 return String.Empty;
1044             }
1045 
1046             // If the column is not filtered, return the filter string unchanged. 
1047             if (!filtered)
1048             {
1049                 return filter;
1050             }
1051 
1052             if (filter.IndexOf(currentColumnFilter) > 0)
1053             {
1054                 // If the current column filter is not the first filter, return
1055                 // the specified filter value without the current column filter 
1056                 // and without the preceding " AND ". 
1057                 return filter.Replace(
1058                     " AND " + currentColumnFilter, String.Empty);
1059             }
1060             else
1061             {
1062                 if (filter.Length > currentColumnFilter.Length)
1063                 {
1064                     // If the current column filter is the first of multiple 
1065                     // filters, return the specified filter value without the 
1066                     // current column filter and without the subsequent " AND ". 
1067                     return filter.Replace(
1068                         currentColumnFilter + " AND ", String.Empty);
1069                 }
1070                 else
1071                 {
1072                     // If the current column filter is the only filter, 
1073                     // return the empty string.
1074                     return String.Empty;
1075                 }
1076             }
1077         }
1078 
1079         /// <summary>
1080         /// Updates the BindingSource.Filter value based on a user selection
1081         /// from the drop-down filter list. 
1082         /// </summary>
1083         private void UpdateFilter()
1084         {
1085             // Continue only if the selection has changed.
1086             if (dropDownListBox.SelectedItem.ToString().Equals(selectedFilterValue))
1087             {
1088                 return;
1089             }
1090 
1091             // Store the new selection value. 
1092             selectedFilterValue = dropDownListBox.SelectedItem.ToString();
1093 
1094             // Cast the data source to an IBindingListView.
1095             IBindingListView data =
1096                 this.DataGridView.DataSource as IBindingListView;
1097 
1098             Debug.Assert(data != null && data.SupportsFiltering,
1099                 "DataSource is not an IBindingListView or does not support filtering");
1100 
1101             // If the user selection is (All), remove any filter currently 
1102             // in effect for the column. 
1103             if (selectedFilterValue.Equals("(All)"))
1104             {
1105                 data.Filter = FilterWithoutCurrentColumn(data.Filter);
1106                 filtered = false;
1107                 currentColumnFilter = String.Empty;
1108                 return;
1109             }
1110 
1111             // Declare a variable to store the filter string for this column.
1112             String newColumnFilter = null;
1113 
1114             // Store the column name in a form acceptable to the Filter property, 
1115             // using a backslash to escape any closing square brackets. 
1116             String columnProperty =
1117                 OwningColumn.DataPropertyName.Replace("]", @"\]");
1118 
1119             // Determine the column filter string based on the user selection.
1120             // For (Blanks) and (NonBlanks), the filter string determines whether
1121             // the column value is null or an empty string. Otherwise, the filter
1122             // string determines whether the column value is the selected value. 
1123             switch (selectedFilterValue)
1124             {
1125                 case "(Blanks)":
1126                     newColumnFilter = String.Format(
1127                         "LEN(ISNULL(CONVERT([{0}],'System.String'),''))=0",
1128                         columnProperty);
1129                     break;
1130                 case "(NonBlanks)":
1131                     newColumnFilter = String.Format(
1132                         "LEN(ISNULL(CONVERT([{0}],'System.String'),''))>0",
1133                         columnProperty);
1134                     break;
1135                 default:
1136                     newColumnFilter = String.Format("[{0}]='{1}'",
1137                         columnProperty,
1138                         ((String)filters[selectedFilterValue])
1139                         .Replace("'", "''"));
1140                     break;
1141             }
1142 
1143             // Determine the new filter string by removing the previous column 
1144             // filter string from the BindingSource.Filter value, then appending 
1145             // the new column filter string, using " AND " as appropriate. 
1146             String newFilter = FilterWithoutCurrentColumn(data.Filter);
1147             if (String.IsNullOrEmpty(newFilter))
1148             {
1149                 newFilter += newColumnFilter;
1150             }
1151             else
1152             {
1153                 newFilter += " AND " + newColumnFilter;
1154             }
1155 
1156 
1157             // Set the filter to the new value.
1158             try
1159             {
1160                 data.Filter = newFilter;
1161             }
1162             catch (InvalidExpressionException ex)
1163             {
1164                 throw new NotSupportedException(
1165                     "Invalid expression: " + newFilter, ex);
1166             }
1167 
1168             // Indicate that the column is currently filtered
1169             // and store the new column filter for use by subsequent
1170             // calls to the FilterWithoutCurrentColumn method. 
1171             filtered = true;
1172             currentColumnFilter = newColumnFilter;
1173         }
1174 
1175         /// <summary>
1176         /// Removes the filter from the BindingSource bound to the specified DataGridView. 
1177         /// </summary>
1178         /// <param name="dataGridView">The DataGridView bound to the BindingSource to unfilter.</param>
1179         public static void RemoveFilter(DataGridView dataGridView)
1180         {
1181             if (dataGridView == null)
1182             {
1183                 throw new ArgumentNullException("dataGridView");
1184             }
1185 
1186             // Cast the data source to a BindingSource.
1187             BindingSource data = dataGridView.DataSource as BindingSource;
1188 
1189             // Confirm that the data source is a BindingSource that 
1190             // supports filtering.
1191             if (data == null ||
1192                 data.DataSource == null ||
1193                 !data.SupportsFiltering)
1194             {
1195                 throw new ArgumentException("The DataSource property of the " +
1196                     "specified DataGridView is not set to a BindingSource " +
1197                     "with a SupportsFiltering property value of true.");
1198             }
1199 
1200             // Ensure that the current row is not the row for new records.
1201             // This prevents the new row from being added when the filter changes.
1202             if (dataGridView.CurrentRow != null && dataGridView.CurrentRow.IsNewRow)
1203             {
1204                 dataGridView.CurrentCell = null;
1205             }
1206 
1207             // Remove the filter. 
1208             data.Filter = null;
1209         }
1210 
1211         /// <summary>
1212         /// Gets a status string for the specified DataGridView indicating the 
1213         /// number of visible rows in the bound, filtered BindingSource, or 
1214         /// String.Empty if all rows are currently visible. 
1215         /// </summary>
1216         /// <param name="dataGridView">The DataGridView bound to the 
1217         /// BindingSource to return the filter status for.</param>
1218         /// <returns>A string in the format "x of y records found" where x is 
1219         /// the number of rows currently displayed and y is the number of rows 
1220         /// available, or String.Empty if all rows are currently displayed.</returns>
1221         public static String GetFilterStatus(DataGridView dataGridView)
1222         {
1223             // Continue only if the specified value is valid. 
1224             if (dataGridView == null)
1225             {
1226                 throw new ArgumentNullException("dataGridView");
1227             }
1228 
1229             // Cast the data source to a BindingSource.
1230             BindingSource data = dataGridView.DataSource as BindingSource;
1231 
1232             // Return String.Empty if there is no appropriate data source or
1233             // there is no filter in effect. 
1234             if (String.IsNullOrEmpty(data.Filter) ||
1235                 data == null ||
1236                 data.DataSource == null ||
1237                 !data.SupportsFiltering)
1238             {
1239                 return String.Empty;
1240             }
1241 
1242             // Retrieve the filtered row count. 
1243             Int32 currentRowCount = data.Count;
1244 
1245             // Retrieve the unfiltered row count by 
1246             // temporarily unfiltering the data.
1247             data.RaiseListChangedEvents = false;
1248             String oldFilter = data.Filter;
1249             data.Filter = null;
1250             Int32 unfilteredRowCount = data.Count;
1251             data.Filter = oldFilter;
1252             data.RaiseListChangedEvents = true;
1253 
1254             Debug.Assert(currentRowCount <= unfilteredRowCount,
1255                 "current count is greater than unfiltered count");
1256 
1257             // Return String.Empty if the filtered and unfiltered counts
1258             // are the same, otherwise, return the status string. 
1259             if (currentRowCount == unfilteredRowCount)
1260             {
1261                 return String.Empty;
1262             }
1263             return String.Format("{0}",
1264                 currentRowCount, unfilteredRowCount);
1265             //of {1} records found
1266         }
1267 
1268         #endregion filtering
1269 
1270         #region button bounds: DropDownButtonBounds, InvalidateDropDownButtonBounds, SetDropDownButtonBounds, AdjustPadding
1271 
1272         /// <summary>
1273         /// The bounds of the drop-down button, or Rectangle.Empty if filtering 
1274         /// is disabled or the button bounds need to be recalculated. 
1275         /// </summary>
1276         private Rectangle dropDownButtonBoundsValue = Rectangle.Empty;
1277 
1278         /// <summary>
1279         /// The bounds of the drop-down button, or Rectangle.Empty if filtering
1280         /// is disabled. Recalculates the button bounds if filtering is enabled
1281         /// and the bounds are empty.
1282         /// </summary>
1283         protected Rectangle DropDownButtonBounds
1284         {
1285             get
1286             {
1287                 if (!FilteringEnabled)
1288                 {
1289                     return Rectangle.Empty;
1290                 }
1291                 if (dropDownButtonBoundsValue == Rectangle.Empty)
1292                 {
1293                     SetDropDownButtonBounds();
1294                 }
1295                 return dropDownButtonBoundsValue;
1296             }
1297         }
1298 
1299         /// <summary>
1300         /// Sets dropDownButtonBoundsValue to Rectangle.Empty if it isn't already empty. 
1301         /// This indicates that the button bounds should be recalculated. 
1302         /// </summary>
1303         private void InvalidateDropDownButtonBounds()
1304         {
1305             if (!dropDownButtonBoundsValue.IsEmpty)
1306             {
1307                 dropDownButtonBoundsValue = Rectangle.Empty;
1308             }
1309         }
1310 
1311         /// <summary>
1312         /// Sets the position and size of dropDownButtonBoundsValue based on the current 
1313         /// cell bounds and the preferred cell height for a single line of header text. 
1314         /// </summary>
1315         private void SetDropDownButtonBounds()
1316         {
1317             // Retrieve the cell display rectangle, which is used to 
1318             // set the position of the drop-down button. 
1319             Rectangle cellBounds =
1320                 this.DataGridView.GetCellDisplayRectangle(
1321                 this.ColumnIndex, -1, false);
1322 
1323             // Initialize a variable to store the button edge length,
1324             // setting its initial value based on the font height. 
1325             Int32 buttonEdgeLength = this.InheritedStyle.Font.Height + 5;
1326 
1327             // Calculate the height of the cell borders and padding.
1328             Rectangle borderRect = BorderWidths(
1329                 this.DataGridView.AdjustColumnHeaderBorderStyle(
1330                 this.DataGridView.AdvancedColumnHeadersBorderStyle,
1331                 new DataGridViewAdvancedBorderStyle(), false, false));
1332             Int32 borderAndPaddingHeight = 2 +
1333                 borderRect.Top + borderRect.Height +
1334                 this.InheritedStyle.Padding.Vertical;
1335             Boolean visualStylesEnabled =
1336                 Application.RenderWithVisualStyles &&
1337                 this.DataGridView.EnableHeadersVisualStyles;
1338             if (visualStylesEnabled)
1339             {
1340                 borderAndPaddingHeight += 3;
1341             }
1342 
1343             // Constrain the button edge length to the height of the 
1344             // column headers minus the border and padding height. 
1345             if (buttonEdgeLength >
1346                 this.DataGridView.ColumnHeadersHeight -
1347                 borderAndPaddingHeight)
1348             {
1349                 buttonEdgeLength =
1350                     this.DataGridView.ColumnHeadersHeight -
1351                     borderAndPaddingHeight;
1352             }
1353 
1354             // Constrain the button edge length to the
1355             // width of the cell minus three.
1356             if (buttonEdgeLength > cellBounds.Width - 3)
1357             {
1358                 buttonEdgeLength = cellBounds.Width - 3;
1359             }
1360 
1361             // Calculate the location of the drop-down button, with adjustments
1362             // based on whether visual styles are enabled. 
1363             Int32 topOffset = visualStylesEnabled ? 4 : 1;
1364             Int32 top = cellBounds.Bottom - buttonEdgeLength - topOffset;
1365             Int32 leftOffset = visualStylesEnabled ? 3 : 1;
1366             Int32 left = 0;
1367             if (this.DataGridView.RightToLeft == RightToLeft.No)
1368             {
1369                 left = cellBounds.Right - buttonEdgeLength - leftOffset;
1370             }
1371             else
1372             {
1373                 left = cellBounds.Left + leftOffset;
1374             }
1375 
1376             // Set the dropDownButtonBoundsValue value using the calculated 
1377             // values, and adjust the cell padding accordingly.  
1378             dropDownButtonBoundsValue = new Rectangle(left, top,
1379                 buttonEdgeLength, buttonEdgeLength);
1380             AdjustPadding(buttonEdgeLength + leftOffset);
1381         }
1382 
1383         /// <summary>
1384         /// Adjusts the cell padding to widen the header by the drop-down button width.
1385         /// </summary>
1386         /// <param name="newDropDownButtonPaddingOffset">The new drop-down button width.</param>
1387         private void AdjustPadding(Int32 newDropDownButtonPaddingOffset)
1388         {
1389             // Determine the difference between the new and current 
1390             // padding adjustment.
1391             Int32 widthChange = newDropDownButtonPaddingOffset -
1392                 currentDropDownButtonPaddingOffset;
1393 
1394             // If the padding needs to change, store the new value and 
1395             // make the change.
1396             if (widthChange != 0)
1397             {
1398                 // Store the offset for the drop-down button separately from 
1399                 // the padding in case the client needs additional padding.
1400                 currentDropDownButtonPaddingOffset =
1401                     newDropDownButtonPaddingOffset;
1402 
1403                 // Create a new Padding using the adjustment amount, then add it
1404                 // to the cell's existing Style.Padding property value. 
1405                 Padding dropDownPadding = new Padding(0, 0, widthChange, 0);
1406                 this.Style.Padding = Padding.Add(
1407                     this.InheritedStyle.Padding, dropDownPadding);
1408             }
1409         }
1410 
1411         /// <summary>
1412         /// The current width of the drop-down button. This field is used to adjust the cell padding.  
1413         /// </summary>
1414         private Int32 currentDropDownButtonPaddingOffset;
1415 
1416         #endregion button bounds
1417 
1418         #region public properties: FilteringEnabled, AutomaticSortingEnabled, DropDownListBoxMaxLines
1419 
1420         /// <summary>
1421         /// Indicates whether filtering is enabled for the owning column. 
1422         /// </summary>
1423         private Boolean filteringEnabledValue = true;
1424 
1425         /// <summary>
1426         /// Gets or sets a value indicating whether filtering is enabled.
1427         /// </summary>
1428         [DefaultValue(true)]
1429         public Boolean FilteringEnabled
1430         {
1431             get
1432             {
1433                 // Return filteringEnabledValue if (there is no DataGridView
1434                 // or if (its DataSource property has not been set. 
1435                 if (this.DataGridView == null ||
1436                     this.DataGridView.DataSource == null)
1437                 {
1438                     return filteringEnabledValue;
1439                 }
1440 
1441                 // if (the DataSource property has been set, return a value that combines 
1442                 // the filteringEnabledValue and BindingSource.SupportsFiltering values.
1443                 BindingSource data = this.DataGridView.DataSource as BindingSource;
1444                 Debug.Assert(data != null);
1445                 return filteringEnabledValue && data.SupportsFiltering;
1446             }
1447             set
1448             {
1449                 // If filtering is disabled, remove the padding adjustment
1450                 // and invalidate the button bounds. 
1451                 if (!value)
1452                 {
1453                     AdjustPadding(0);
1454                     InvalidateDropDownButtonBounds();
1455                 }
1456 
1457                 filteringEnabledValue = value;
1458             }
1459         }
1460 
1461         /// <summary>
1462         /// Indicates whether automatic sorting is enabled. 
1463         /// </summary>
1464         private Boolean automaticSortingEnabledValue = true;
1465 
1466         /// <summary>
1467         /// Gets or sets a value indicating whether automatic sorting is enabled for the owning column. 
1468         /// </summary>
1469         [DefaultValue(true)]
1470         public Boolean AutomaticSortingEnabled
1471         {
1472             get
1473             {
1474                 return automaticSortingEnabledValue;
1475             }
1476             set
1477             {
1478                 automaticSortingEnabledValue = value;
1479                 if (OwningColumn != null)
1480                 {
1481                     if (value)
1482                     {
1483                         OwningColumn.SortMode = DataGridViewColumnSortMode.Programmatic;
1484                     }
1485                     else
1486                     {
1487                         OwningColumn.SortMode = DataGridViewColumnSortMode.NotSortable;
1488                     }
1489                 }
1490             }
1491         }
1492 
1493         /// <summary>
1494         /// The maximum number of lines in the drop-down list. 
1495         /// </summary>
1496         private Int32 dropDownListBoxMaxLinesValue = 30;
1497 
1498         /// <summary>
1499         /// Gets or sets the maximum number of lines to display in the drop-down filter list. 
1500         /// The actual height of the drop-down list is constrained by the DataGridView height. 
1501         /// </summary>
1502         [DefaultValue(30)]
1503         public Int32 DropDownListBoxMaxLines
1504         {
1505             get { return dropDownListBoxMaxLinesValue; }
1506             set { dropDownListBoxMaxLinesValue = value; }
1507         }
1508 
1509         #endregion public properties
1510 
1511         /// <summary>
1512         /// Represents a ListBox control used as a drop-down filter list
1513         /// in a DataGridView control.
1514         /// </summary>
1515         private class FilterListBox : ListBox
1516         {
1517             /// <summary>
1518             /// Initializes a new instance of the FilterListBox class.
1519             /// </summary>
1520             public FilterListBox()
1521             {
1522                 Visible = false;
1523                 IntegralHeight = true;
1524                 BorderStyle = BorderStyle.FixedSingle;
1525                 TabStop = false;
1526             }
1527 
1528             /// <summary>
1529             /// Indicates that the FilterListBox will handle (or ignore) all 
1530             /// keystrokes that are not handled by the operating system. 
1531             /// </summary>
1532             /// <param name="keyData">A Keys value that represents the keyboard input.</param>
1533             /// <returns>true in all cases.</returns>
1534             protected override bool IsInputKey(Keys keyData)
1535             {
1536                 return true;
1537             }
1538 
1539             /// <summary>
1540             /// Processes a keyboard message directly, preventing it from being
1541             /// intercepted by the parent DataGridView control.
1542             /// </summary>
1543             /// <param name="m">A Message, passed by reference, that 
1544             /// represents the window message to process.</param>
1545             /// <returns>true if the message was processed by the control;
1546             /// otherwise, false.</returns>
1547             protected override bool ProcessKeyMessage(ref Message m)
1548             {
1549                 return ProcessKeyEventArgs(ref m);
1550             }
1551 
1552         }
1553 
1554     }
1555 
1556     public class DataGridViewAutoFilterTextBoxColumn : DataGridViewTextBoxColumn
1557     {
1558         /// <summary>
1559         /// Initializes a new instance of the DataGridViewAutoFilterTextBoxColumn class.
1560         /// </summary>
1561         public DataGridViewAutoFilterTextBoxColumn()
1562             : base()
1563         {
1564             base.DefaultHeaderCellType = typeof(DataGridViewAutoFilterColumnHeaderCell);
1565             base.SortMode = DataGridViewColumnSortMode.Programmatic;
1566         }
1567 
1568         #region public properties that hide inherited, non-virtual properties: DefaultHeaderCellType and SortMode
1569 
1570         /// <summary>
1571         /// Returns the AutoFilter header cell type. This property hides the 
1572         /// non-virtual DefaultHeaderCellType property inherited from the 
1573         /// DataGridViewBand class. The inherited property is set in the 
1574         /// DataGridViewAutoFilterTextBoxColumn constructor. 
1575         /// </summary>
1576         [EditorBrowsable(EditorBrowsableState.Never), Browsable(false),
1577         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
1578         public new Type DefaultHeaderCellType
1579         {
1580             get
1581             {
1582                 return typeof(DataGridViewAutoFilterColumnHeaderCell);
1583             }
1584         }
1585 
1586         /// <summary>
1587         /// Gets or sets the sort mode for the column and prevents it from being 
1588         /// set to Automatic, which would interfere with the proper functioning 
1589         /// of the drop-down button. This property hides the non-virtual 
1590         /// DataGridViewColumn.SortMode property from the designer. The inherited 
1591         /// property is set in the DataGridViewAutoFilterTextBoxColumn constructor.
1592         /// </summary>
1593         [EditorBrowsable(EditorBrowsableState.Advanced), Browsable(false)]
1594         [DefaultValue(DataGridViewColumnSortMode.Programmatic)]
1595         public new DataGridViewColumnSortMode SortMode
1596         {
1597             get
1598             {
1599                 return base.SortMode;
1600             }
1601             set
1602             {
1603                 if (value == DataGridViewColumnSortMode.Automatic)
1604                 {
1605                     throw new InvalidOperationException(
1606                         "A SortMode value of Automatic is incompatible with " +
1607                         "the DataGridViewAutoFilterColumnHeaderCell type. " +
1608                         "Use the AutomaticSortingEnabled property instead.");
1609                 }
1610                 else
1611                 {
1612                     base.SortMode = value;
1613                 }
1614             }
1615         }
1616 
1617         #endregion
1618 
1619         #region public properties: FilteringEnabled, AutomaticSortingEnabled, DropDownListBoxMaxLines
1620 
1621         /// <summary>
1622         /// Gets or sets a value indicating whether filtering is enabled for this column. 
1623         /// </summary>
1624         [DefaultValue(true)]
1625         public Boolean FilteringEnabled
1626         {
1627             get
1628             {
1629                 // Return the header-cell value.
1630                 return ((DataGridViewAutoFilterColumnHeaderCell)HeaderCell)
1631                     .FilteringEnabled;
1632             }
1633             set
1634             {
1635                 // Set the header-cell property. 
1636                 ((DataGridViewAutoFilterColumnHeaderCell)HeaderCell)
1637                     .FilteringEnabled = value;
1638             }
1639         }
1640 
1641         /// <summary>
1642         /// Gets or sets a value indicating whether automatic sorting is enabled for this column. 
1643         /// </summary>
1644         [DefaultValue(true)]
1645         public Boolean AutomaticSortingEnabled
1646         {
1647             get
1648             {
1649                 // Return the header-cell value.
1650                 return ((DataGridViewAutoFilterColumnHeaderCell)HeaderCell)
1651                     .AutomaticSortingEnabled;
1652             }
1653             set
1654             {
1655                 // Set the header-cell property.
1656                 ((DataGridViewAutoFilterColumnHeaderCell)HeaderCell)
1657                     .AutomaticSortingEnabled = value;
1658             }
1659         }
1660 
1661         /// <summary>
1662         /// Gets or sets the maximum height of the drop-down filter list for this column. 
1663         /// </summary>
1664         [DefaultValue(20)]
1665         public Int32 DropDownListBoxMaxLines
1666         {
1667             get
1668             {
1669                 // Return the header-cell value.
1670                 return ((DataGridViewAutoFilterColumnHeaderCell)HeaderCell)
1671                     .DropDownListBoxMaxLines;
1672             }
1673             set
1674             {
1675                 // Set the header-cell property.
1676                 ((DataGridViewAutoFilterColumnHeaderCell)HeaderCell)
1677                     .DropDownListBoxMaxLines = value;
1678             }
1679         }
1680 
1681         #endregion public properties
1682 
1683         #region public, static, convenience methods: RemoveFilter and GetFilterStatus
1684 
1685         /// <summary>
1686         /// Removes the filter from the BindingSource bound to the specified DataGridView. 
1687         /// </summary>
1688         /// <param name="dataGridView">The DataGridView bound to the BindingSource to unfilter.</param>
1689         public static void RemoveFilter(DataGridView dataGridView)
1690         {
1691             DataGridViewAutoFilterColumnHeaderCell.RemoveFilter(dataGridView);
1692         }
1693 
1694         /// <summary>
1695         /// Gets a status string for the specified DataGridView indicating the 
1696         /// number of visible rows in the bound, filtered BindingSource, or 
1697         /// String.Empty if all rows are currently visible. 
1698         /// </summary>
1699         /// <param name="dataGridView">The DataGridView bound to the 
1700         /// BindingSource to return the filter status for.</param>
1701         /// <returns>A string in the format "x of y records found" where x is 
1702         /// the number of rows currently displayed and y is the number of rows 
1703         /// available, or String.Empty if all rows are currently displayed.</returns>
1704         public static String GetFilterStatus(DataGridView dataGridView)
1705         {
1706             return DataGridViewAutoFilterColumnHeaderCell.GetFilterStatus(dataGridView);
1707         }
1708 
1709         #endregion
1710     }
1711 
1712     public class DataGridViewComboEditBoxColumn : DataGridViewComboBoxColumn
1713     {
1714         public DataGridViewComboEditBoxColumn()
1715         {
1716             DataGridViewComboEditBoxCell obj = new DataGridViewComboEditBoxCell();
1717             this.CellTemplate = obj;
1718         }
1719         public class DataGridViewComboEditBoxCell : DataGridViewComboBoxCell
1720         {
1721             public override void InitializeEditingControl(int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
1722             {
1723                 base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle);
1724 
1725                 ComboBox comboBox = (ComboBox)base.DataGridView.EditingControl;
1726 
1727                 if (comboBox != null)
1728                 {
1729                     comboBox.DropDownStyle = ComboBoxStyle.DropDown;
1730                     comboBox.AutoCompleteMode = AutoCompleteMode.Suggest;
1731                     comboBox.Validating += new CancelEventHandler(comboBox_Validating);
1732                 }
1733             }
1734 
1735             //protected override object GetFormattedValue(object value, int rowIndex, ref DataGridViewCellStyle cellStyle, TypeConverter valueTypeConverter, TypeConverter formattedValueTypeConverter, DataGridViewDataErrorContexts context)
1736             //{
1737             //    if (value != null)
1738             //    {
1739             //        if (value.ToString().Trim() != string.Empty)
1740             //        {
1741             //            if (Items.IndexOf(value) == -1)
1742             //            {
1743             //                Items.Add(value);
1744             //                //DataGridViewComboBoxColumn col = (DataGridViewComboBoxColumn)OwningColumn; 
1745             //                //col.Items.Add(value); 
1746             //            }
1747             //        }
1748             //    }
1749             //    return base.GetFormattedValue(value, rowIndex, ref cellStyle, valueTypeConverter, formattedValueTypeConverter, context);
1750             //}
1751 
1752             void comboBox_Validating(object sender, System.ComponentModel.CancelEventArgs e)
1753             {
1754                 DataGridViewComboBoxEditingControl cbo = (DataGridViewComboBoxEditingControl)sender;
1755                 if (cbo.Text.Trim() == string.Empty) return;
1756 
1757                 DataGridView grid = cbo.EditingControlDataGridView;
1758                 object value = cbo.Text;
1759 
1760                 // Add value to list if not there 
1761                 if (cbo.Items.IndexOf(value) == -1)
1762                 {
1763                     DataGridViewComboBoxColumn cboCol = (DataGridViewComboBoxColumn)grid.Columns[grid.CurrentCell.ColumnIndex];
1764                     // Must add to both the current combobox as well as the template, to avoid duplicate entries 
1765                     cbo.Items.Add(value);
1766                     //cboCol.Items.Add(value); 
1767                     grid.CurrentCell.Value = value;
1768                 }
1769             }
1770         }
1771     }
1772     /// <summary>
1773     /// 调用时所用*注意:筛选后Count数据需要用DataBindingComplete事件
1774     /// </summary>
1775     public class DataGridViewFunction
1776     {
1777         /// <summary>
1778         /// 查询时加载时所用-生成ComBox并返回行数.每查询一次执行一次
1779         /// </summary>
1780         /// <param name="DGV"></param>
1781         /// <returns></returns>
1782         public string GridViewHeaderFilter(DataGridView DGV)
1783         {
1784             string Number = "0";//默认数量为0
1785             if (DGV.DataSource != null && DGV.Columns.Count > 0)
1786             {
1787                 foreach (DataGridViewColumn col in DGV.Columns)
1788                 {
1789                     col.HeaderCell = new
1790                         DataGridViewAutoFilter.DataGridViewAutoFilterColumnHeaderCell(col.HeaderCell);
1791                 }
1792                 DGV.AutoResizeColumns();
1793                 DataGridViewAutoFilter.DataGridViewAutoFilterColumnHeaderCell filterCell =DGV.CurrentCell.OwningColumn.HeaderCell as DataGridViewAutoFilter.DataGridViewAutoFilterColumnHeaderCell;
1794                 if (filterCell != null)
1795                 {
1796                     filterCell.ShowDropDownList();
1797                     //e.Handled = true;
1798                 }
1799                 String filterStatus = DataGridViewAutoFilter.DataGridViewAutoFilterColumnHeaderCell.GetFilterStatus(DGV);
1800                 if (String.IsNullOrEmpty(filterStatus))
1801                 {
1802                     Number = DGV.RowCount.ToString();
1803                 }
1804                 else
1805                 {
1806                     Number = filterStatus;
1807                 }
1808             }
1809             return Number;
1810         }
1811         /// <summary>
1812         /// 返回GridView数据行数
1813         /// </summary>
1814         /// <param name="DGV"></param>
1815         /// <returns></returns>
1816         public string GridViewDataCount(DataGridView DGV)
1817         {
1818             return DGV.RowCount.ToString();
1819         }
1820         /// <summary>
1821         /// DataGridView填充数据
1822         /// </summary>
1823         /// <param name="dt"></param>
1824         /// <param name="DGV"></param>
1825         public void  GridViewDataLoad(DataTable dt, DataGridView DGV)
1826         {
1827                 DGV.DataSource = null;
1828                 BindingSource dataSource = new BindingSource(dt, null); ;
1829                 DGV.DataSource = dataSource;
1830               
1831         }
1832         
1833     }
1834 }
View Code

调用代码如下

 1 using System;
 2 using System.Collections.Generic;
 3 using System.ComponentModel;
 4 using System.Data;
 5 using System.Drawing;
 6 using System.Linq;
 7 using System.Text;
 8 using System.Windows.Forms;
 9 using DataGridViewAutoFilter;
10 
11 namespace WindowsFormsApplication4
12 {
13     public partial class Form1 : Form
14     {
15         public Form1()
16         {
17             InitializeComponent();
18         }
19         MESDB.MESDB GetDB = new MESDB.MESDB();//作者自用数据库链接接口(WebService)
20         DataGridViewAutoFilter.DataGridViewFunction Get = new DataGridViewFunction();
21         /// <summary>
22         /// 窗体加载事件-并加载数据
23         /// </summary>
24         /// <param name="sender"></param>
25         /// <param name="e"></param>
26         private void Form1_Load(object sender, EventArgs e)
27         {
28             string Sql = "select c.Product_ID as '产品编号',f.Pn_Type as '生产类型',concat(c.Hold_Stage,'[',d.Stage_Name,']') as 'Hold站点',c.Stage_OldStatus as '旧状态' ,concat(c.Line_Type,'[',e.Type_Remark,']' )as '所属区域',c.Hold_Rmark as 'Hold原因' , c.Hold_Time as 'Hold时间' ,c.Hold_User as '操作用户' ,c.Stage_Status as '产品状态' ,substr(c.LevelProductName,1,8) as 'UnitP/N',c.LevelProductName as 'Hold品名',g.TESTTIME as 'CowTestTime' ,c.Change_Level as '升/降档',c.Release_Remark as '释放备注' ,c.Release_Time as '释放时间' , c.Release_User as '释放用户',c.Release_Owner as '释放部门',c.Transfer_Owner as '转移理由',c.Transfer_Time as '转移时间' ,c.Transfer_User as '转移用户',c.Exception_Type as '异常归类',c.Level_Handling as '升降档归类',c.Parameter_Type as '异常参数',c.Department_Owner as '责任归类',c.Treat_Remark as '归类备注',c.Remark_User as '归类用户',c.Remark_Time  as '归类时间',c.Hold_Type as 'Hold类型' from   mes.MES_Chip_Stage as d,mes.MES_Chip_LineType e,mes.MES_Lot_Attribute as f,mes.MES_Qc_Hold  as c left join eda.cow_probe_sample_test_summary as g on c.Product_ID=g.CHIP_WaferID   where f.Lot_Attribute=substr(c.Product_ID,1,1) and   c.Hold_Stage=d.Stage_Code  and c.Line_Type=e.Line_Type  and c.Line_Type='PV' and c.Transfer_Time  between '2016/05/08 17:52:29' and '2016/06/07 17:52:29' ";
29             DataTable dt = GetDB.MySqlDBSelct(Sql).Tables[0];
30             Get.GridViewDataLoading(dt, dataGridView1);//填充DataGridView
31             label1.Text = Get.GridViewHeaderFilter(dataGridView1);//标题添加ComBox并返回行数
32            
33         }
34         private void dataGridView1_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
35         {
36 
37             label1.Text = Get.GridViewDataCount(dataGridView1);//筛选时动态加载行数
38           
39         }
40     }
41 }
View Code

 

推荐阅读