C# 需要关于过滤DataGrid的建议吗

C# 需要关于过滤DataGrid的建议吗,c#,datagrid,filter,C#,Datagrid,Filter,我正在使用.NET3.5、C#和WinForms 我的网格有很多列:SellerName、BuyerName、LoadType、LoadName、DriverName、CarSerialNumber等。我想过滤BindingSource。我使用下拉列表中填充网格单元格值的组合框来实现这一点,但这并不实用,而且会导致表单外观不好 我需要的建议是什么是最好的方式,让用户选择网格的值,然后用一个按钮过滤。我可以在Excel中这样做吗?列标题上有一个按钮,当用户按下它时,它会显示一个带有复选框的小菜单。

我正在使用.NET3.5、C#和WinForms

我的网格有很多列:SellerName、BuyerName、LoadType、LoadName、DriverName、CarSerialNumber等。我想过滤BindingSource。我使用下拉列表中填充网格单元格值的组合框来实现这一点,但这并不实用,而且会导致表单外观不好

我需要的建议是什么是最好的方式,让用户选择网格的值,然后用一个按钮过滤。我可以在Excel中这样做吗?列标题上有一个按钮,当用户按下它时,它会显示一个带有复选框的小菜单。当用户检查任何值并按下按钮时,它开始过滤

请给我一些建议

这是Excel的图片:

谢谢

嗯,
首先,您应该创建自定义的filter usercontrol,就像您希望在excel中创建的那样

其次,这并不容易,但您可以向网格中添加筛选按钮(只需执行
grid.Controls.add(…)
),并通过覆盖
DatagridView
OnColumnWidthChanged/OnColumnHeadersWeightChanged
使其与列标题对齐

最后,当用户单击filter按钮时,您可以打开一个
ToolStripDropDown
,其中嵌入了您的自定义筛选器,我的意思与此类似(显然是使用控件而不是listview):


编辑:

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;
    }
}
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);
    }
}
下面是一个(工作)代码示例:

自定义列标题单元格类:

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;
    }
}
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);
    }
}
公共类DataGridWithFilter:DataGridView
{
已添加受保护的覆盖无效OnColumnAdded(DataGridViewColumnEventArgs e)
{
var header=新的DataGridFilterHeader();
header.FilterButtonClicked+=新事件处理程序(header_FilterButtonClicked);
e、 Column.HeaderCell=标题;
碱基。添加的癌柱(e);
}
无效标头\u FilterButtonClicked(对象发送器,列FilterClickedEventarg e)
{
//在屏幕左下角打开一个弹出窗口
//过滤按钮
//这里我们添加了一个简单的hello world文本框,但您应该添加您的过滤器控件
TextBox innerCtrl=新建TextBox();
innerCtrl.Text=“你好,世界!”;
innerCtrl.Size=新系统.Drawing.Size(100,30);
var popup=新的ToolStripDropDown();
popup.AutoSize=false;
popup.Margin=Padding.Empty;
popup.Padding=Padding.Empty;
ToolStripControlHost主机=新的ToolStripControlHost(innerCtrl);
host.Margin=Padding.Empty;
host.Padding=Padding.Empty;
host.AutoSize=false;
host.Size=innerCtrl.Size;
popup.Size=innerCtrl.Size;
弹出.Items.Add(主机);
//显示弹出窗口
显示(这个,e.ButtonRectangle.X,e.ButtonRectangle.Bottom);
}
}
结果:

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

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

这是一个完整的VS2008项目示例(带有自定义过滤器的DataGrid,而不仅仅是“Hello World”):-->

我无法添加按钮它位于网格上,并且我只希望在所有列标题文本的左侧有一个。datagridview1.Controls.Add(btnFiler);您(部分)是对的,我使用自定义的
DataGridViewColumnHeaderCell
实现了您需要的功能。看看我的编辑,我真的希望这有帮助(有点累)哇!太晚了,我要睡个好觉,明天再做。你是最棒的。我真高兴。我试图做一些事情,因为“14小时前回答”,但没有。。。。非常感谢。我无法使用此代码:(我不知道在哪里插入和如何调用,只需使用我发布的3个类创建3个文件。然后使用
DataGridWithFilter
而不是通常的
DataGridView
。在项目编译后,您甚至应该在designer工具箱中看到一个
DataGridWithFilter
项,因此,如果需要,您可以将其拖放到表单上。否则,以编程方式将其添加到表单中。