Нужен совет по фильтрации DataGrid - PullRequest
0 голосов
/ 22 ноября 2010

Я использую .NET 3.5, C # и WinForms.

В моей сетке много столбцов: SellerName, BuyerName, LoadType, LoadName, DriverName, CarSerialNumber и т. Д. Я хочу отфильтровать BindingSource. Я сделал это, используя ComboBoxes, который заполняется в DropDown значениями ячеек сетки, но это не практично и создает плохую форму.

Мне нужен совет о том, как лучше всего позволить пользователю выбирать значения сетки, а затем фильтровать с помощью кнопки. Можно ли сделать это как в Excel? В заголовке столбца есть кнопка, и когда пользователь нажимает ее, она показывает небольшое меню с отмеченным списком. Когда пользователь проверяет какие-либо значения и нажимает кнопку, начинается фильтрация.

Пожалуйста, сообщите мне что-нибудь.

Это изображение Excel:

Screenshot

Спасибо!

1 Ответ

1 голос
/ 22 ноября 2010

Ну
Прежде всего вы должны создать свой пользовательский фильтр 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);
    }
}

Результат:

Filter Image


РЕДАКТИРОВАТЬ 2:

Вот полный пример проекта VS2008 (DataGrid с настроенным фильтром, а не просто «Hello World»): -> http://www.mediafire.com/?s6o8jmpzh0t82v2

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...