需要有关过滤DataGrid的建议

时间:2010-11-22 08:35:06

标签: c# datagrid filter

我正在使用.NET 3.5,C#和WinForms。

我的网格有很多列:SellerName,BuyerName,LoadType,LoadName,DriverName,CarSerialNumber等。我想过滤BindingSource。我使用ComboBoxes做了这个,它在DropDown上填充了网格单元格的值,但它不实用并且造成了一个看起来很糟糕的形式。

我需要建议让用户选择网格值然后使用按钮过滤的最佳方法。我可以像在Excel中一样制作吗?列标题上有一个按钮,当用户按下它时,它会显示一个带有选中列表框的小菜单。当用户检查任何值并按下按钮时,它开始过滤。

请告诉我一些事情。

这是Excel的图片:

Screenshot

谢谢!

1 个答案:

答案 0 :(得分:1)

那么,
首先,您应该创建自定义过滤器usercontrol,与您在excel中的过滤器一样。

其次,这并不容易,但您可以向网格添加过滤器按钮(只需执行grid.Controls.Add(...))并通过覆盖OnColumnWidthChanged/OnColumnHeadersHeightChanged的{​​{1}}使其与列标题保持一致

最后,当用户点击过滤器按钮时,您可以打开DatagridView并在其中嵌入自定义过滤器,我的意思与此答案类似(显然是使用您的控件而不是列表视图):
DropDown Menu with ScrollBar in .NET


编辑:

这是一个(工作)代码示例:

自定义列标题单元格类:

ToolStripDropDown

自定义事件参数:

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));
    }
}

DataGridView覆盖:

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;
    }
}

结果:

Filter Image


编辑2:

这是一个完整的VS2008项目示例(带有自定义过滤器的DataGrid,而不仅仅是“Hello World”): - &gt; http://www.mediafire.com/?s6o8jmpzh0t82v2