Ну
Прежде всего вы должны создать свой пользовательский фильтр usercontrol, настолько похожий, насколько вы хотите, на тот, что в Excel.
Во-вторых, это нелегко сделать, но вы можете добавить кнопки фильтра в сетку (просто сделав grid.Controls.Add(...)
) и выровнять их по заголовкам столбцов, переопределив OnColumnWidthChanged/OnColumnHeadersHeightChanged
из DatagridView
.
Наконец, когда пользователь нажимает кнопку фильтра, вы можете открыть ToolStripDropDown
со встроенным в него пользовательским фильтром, я имею в виду нечто похожее на этот ответ (очевидно, с вашим контролем вместо просмотра списка):
Меню DropDown с полосой прокрутки в .NET
РЕДАКТИРОВАТЬ:
Вот (рабочий) пример кода:
Класс ячейки пользовательского заголовка столбца:
public class DataGridFilterHeader : DataGridViewColumnHeaderCell
{
PushButtonState currentState = PushButtonState.Normal;
Point cellLocation;
Rectangle buttonRect;
public event EventHandler<ColumnFilterClickedEventArg> FilterButtonClicked;
protected override void Paint(Graphics graphics,
Rectangle clipBounds,
Rectangle cellBounds,
int rowIndex,
DataGridViewElementStates dataGridViewElementState,
object value,
object formattedValue,
string errorText,
DataGridViewCellStyle cellStyle,
DataGridViewAdvancedBorderStyle advancedBorderStyle,
DataGridViewPaintParts paintParts)
{
base.Paint(graphics, clipBounds,
cellBounds, rowIndex,
dataGridViewElementState, value,
formattedValue, errorText,
cellStyle, advancedBorderStyle, paintParts);
int width = 20; // 20 px
buttonRect = new Rectangle(cellBounds.X + cellBounds.Width - width, cellBounds.Y, width, cellBounds.Height);
cellLocation = cellBounds.Location;
// to set image/ or some other properties to the filter button look at DrawButton overloads
ButtonRenderer.DrawButton(graphics,
buttonRect,
"F",
this.DataGridView.Font,
false,
currentState);
}
protected override void OnMouseDown(DataGridViewCellMouseEventArgs e)
{
if (this.IsMouseOverButton(e.Location))
currentState = PushButtonState.Pressed;
base.OnMouseDown(e);
}
protected override void OnMouseUp(DataGridViewCellMouseEventArgs e)
{
if (this.IsMouseOverButton(e.Location))
{
currentState = PushButtonState.Normal;
this.OnFilterButtonClicked();
}
base.OnMouseUp(e);
}
private bool IsMouseOverButton(Point e)
{
Point p = new Point(e.X + cellLocation.X, e.Y + cellLocation.Y);
if (p.X >= buttonRect.X && p.X <= buttonRect.X + buttonRect.Width &&
p.Y >= buttonRect.Y && p.Y <= buttonRect.Y + buttonRect.Height)
{
return true;
}
return false;
}
protected virtual void OnFilterButtonClicked()
{
if (this.FilterButtonClicked != null)
this.FilterButtonClicked(this, new ColumnFilterClickedEventArg(this.ColumnIndex, this.buttonRect));
}
}
Аргументы пользовательских событий:
public class ColumnFilterClickedEventArg : EventArgs
{
public int ColumnIndex { get; private set; }
public Rectangle ButtonRectangle { get; private set; }
public ColumnFilterClickedEventArg(int colIndex, Rectangle btnRect)
{
this.ColumnIndex = colIndex;
this.ButtonRectangle = btnRect;
}
}
Переопределение DataGridView:
public class DataGridWithFilter : DataGridView
{
protected override void OnColumnAdded(DataGridViewColumnEventArgs e)
{
var header = new DataGridFilterHeader();
header.FilterButtonClicked += new EventHandler<ColumnFilterClickedEventArg>(header_FilterButtonClicked);
e.Column.HeaderCell = header;
base.OnColumnAdded(e);
}
void header_FilterButtonClicked(object sender, ColumnFilterClickedEventArg e)
{
// open a popup on the bottom-left corner of the
// filter button
// here's we add a simple hello world textbox, but you should add your filter control
TextBox innerCtrl = new TextBox();
innerCtrl.Text = "Hello World !";
innerCtrl.Size = new System.Drawing.Size(100, 30);
var popup = new ToolStripDropDown();
popup.AutoSize = false;
popup.Margin = Padding.Empty;
popup.Padding = Padding.Empty;
ToolStripControlHost host = new ToolStripControlHost(innerCtrl);
host.Margin = Padding.Empty;
host.Padding = Padding.Empty;
host.AutoSize = false;
host.Size = innerCtrl.Size;
popup.Size = innerCtrl.Size;
popup.Items.Add(host);
// show the popup
popup.Show(this, e.ButtonRectangle.X, e.ButtonRectangle.Bottom);
}
}
Результат:
РЕДАКТИРОВАТЬ 2:
Вот полный пример проекта VS2008 (DataGrid с настроенным фильтром, а не просто «Hello World»): -> http://www.mediafire.com/?s6o8jmpzh0t82v2