需要关于过滤DataGrid的建议 [英] Need advice about filtering DataGrid

查看:241
本文介绍了需要关于过滤DataGrid的建议的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我的网格有很多列:SellerName,BuyerName,LoadType,LoadName,DriverName,CarSerialNumber,我想过滤BindingSource。我使用了ComboBoxes,它使用了GridDelection的DropDown,但它不实用,并且使用了一个坏的形式。



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



请指教一下。



这是Excel的图片:





谢谢!

解决方案

嗯,

首先你应该创建你的自定义过滤器usercontrol,对于excel中的一个。



其次,这不容易,但您可以向网格添加过滤器按钮(只需执行 grid.Controls .Add(...)),并通过覆盖保持它们与列的标题对齐OnColumnWidthChanged / OnColumnHeadersHeightChanged DatagridView



最后,当用户点击过滤器按钮时,您可以打开一个 ToolStripDropDown 嵌入其中的自定义过滤器,我的意思是类似于这个答案(显然是用你的控制而不是listview):


I'm using .NET 3.5, C#, and WinForms.

My grid has lots of columns: SellerName, BuyerName, LoadType, LoadName, DriverName, CarSerialNumber, etc. I want to filter the BindingSource. I did this using ComboBoxes which is filled on DropDown with the grid cells' values, but it's not practical and makes for a bad-looking form.

I need advice on what is the best way to let the user choose values of the grid and then filter with a button. Can I make it like in Excel? There is a button on the column header, and when the user presses it, it shows a little menu with a checked list box. When the user checks any values and press a button it begins filtering.

Please advise me something.

This is pic of Excel:

Thanks!

解决方案

Well,
first of all you should create your custom filter usercontrol, as similar as you wish to the one in excel.

Secondly, it's not easy to do, but you could add filter buttons to the grid (simply doing grid.Controls.Add(...)) and keep them aligned with columns' headers by overriding OnColumnWidthChanged/OnColumnHeadersHeightChanged of DatagridView.

Finally, when user clicks on filter button, you can open a ToolStripDropDown with your custom filter embedded in it, I mean something similar to this answer (obviously with your control instead of the listview):
DropDown Menu with ScrollBar in .NET


EDIT:

Here's a (working) code sample:

Custom Column Header Cell Class:

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

Custom Event Args:

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 Override:

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

Result:


EDIT 2:

Here's a full VS2008 project sample (DataGrid with customized filter, not just "Hello World"): --> http://www.mediafire.com/?s6o8jmpzh0t82v2

这篇关于需要关于过滤DataGrid的建议的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆