FilterableHeaderCell

  • 定义FilterableHeaderCell
#region FilterableHeaderCell
public class FilterableHeaderCell : DataGridViewColumnHeaderCell
{
    private Rectangle dropdownButtonRect = Rectangle.Empty;
    private bool dropdownOpen = false;
    private ContextMenuStrip filterMenu = new ContextMenuStrip();
    public HashSet<string> selectedFilters = new HashSet<string>();
    private List<string> allFilterValues = new List<string>();
    public List<DataGridViewRow> listAllRow = new List<DataGridViewRow>();
    private string headerText = "";

    public FilterableHeaderCell()
    {
        filterMenu.ItemClicked += FilterMenu_ItemClicked;
        filterMenu.Closing += FilterMenu_Closing;
    }

    public FilterableHeaderCell(string headerText)
    {
        this.headerText = headerText;
        filterMenu.ItemClicked += FilterMenu_ItemClicked;
        filterMenu.Closing += FilterMenu_Closing;
    }

    public void Rest()
    {
        try
        {
            listAllRow.Clear();
            foreach (DataGridViewRow row in this.DataGridView.Rows)
            {
                listAllRow.Add(row);
            }

            filterMenu.Items.Clear();
            selectedFilters.Clear();
            allFilterValues.Clear();
        }
        catch (Exception ex)
        {
            LogHelper.Error(ex.Message + ";" + ex.StackTrace);
        }
    }

    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)
    {
        try
        {
            string showValue = string.IsNullOrEmpty(this.headerText) ? value.ToString() : this.headerText;
            //string headerText = this.DataGridView.Columns[this.ColumnIndex].HeaderText;
            // Draw the default header cell
            base.Paint(graphics, clipBounds, cellBounds, rowIndex, dataGridViewElementState, showValue,
                showValue, errorText, cellStyle, advancedBorderStyle, paintParts);

            int width = 8;
            int height = 8;

            // Define the rectangle for the dropdown button relative to the cellBounds.
            dropdownButtonRect = new Rectangle(
                cellBounds.Right - width - 2, // 15 pixels from the right edge of the cellBounds
                cellBounds.Bottom - cellBounds.Height / 2 - height / 2,    // 5 pixels from the top edge of the cellBounds
                width,                    // 10 pixels wide
               height// The height is the cell height minus 10 pixels
            );

            // Draw a custom dropdown button

            /*// Draw the dropdown button
            ControlPaint.DrawComboButton(graphics, dropdownButtonRect, ButtonState.Normal);
            if (dropdownOpen)
            {
                ControlPaint.DrawComboButton(graphics, dropdownButtonRect, ButtonState.Pushed);
            }*/
            graphics.FillRectangle(Brushes.LightGray, dropdownButtonRect); // Change the color as needed
            graphics.DrawRectangle(Pens.Black, dropdownButtonRect); // Draw border

            // Create the path for the arrow
            var arrowX = dropdownButtonRect.Left + dropdownButtonRect.Width / 2;
            var arrowY = dropdownButtonRect.Top + dropdownButtonRect.Height / 2;
            var arrowPath = new GraphicsPath();
            arrowPath.AddLine(arrowX - 3, arrowY - 1, arrowX + 3, arrowY - 1);
            arrowPath.AddLine(arrowX + 3, arrowY - 1, arrowX, arrowY + 2);
            arrowPath.CloseFigure();

            // Draw the arrow
            graphics.FillPath(Brushes.Black, arrowPath); // Change the color as needed

            if (dropdownOpen)
            {
                // Modify the appearance for when the dropdown is open
                graphics.FillRectangle(Brushes.LightGray, dropdownButtonRect); // Change as needed
                graphics.FillPath(Brushes.Black, arrowPath); // Change the color as needed
            }
        }
        catch (Exception ex)
        {
            LogHelper.Error(ex.Message + ";" + ex.StackTrace);
        }

    }

    protected override void OnMouseDown(DataGridViewCellMouseEventArgs e)
    {
        try
        {
            // 转换坐标,使之相对于列头单元格
            Point cellRelativeCoords = new Point(e.X + this.DataGridView.GetCellDisplayRectangle(e.ColumnIndex, -1, true).Left, e.Y);

            // 创建一个比可视按钮大的点击检测区域
            Rectangle largerClickArea = new Rectangle(
                dropdownButtonRect.Left, // 扩大点击区域
                dropdownButtonRect.Top,  // 扩大点击区域
                dropdownButtonRect.Width, // 扩大点击区域
                dropdownButtonRect.Height  // 扩大点击区域
            );

            if (largerClickArea.Contains(cellRelativeCoords))
            {

                this.DataGridView.InvalidateCell(this);
                // 变更下拉按钮的状态

                // 显示筛选菜单
                ShowFilterMenu();
                return;
            }
            base.OnMouseDown(e);
        }
        catch (Exception ex)
        {
            LogHelper.Error(ex.Message + ";" + ex.StackTrace);
        }
    }

    protected override void OnMouseUp(DataGridViewCellMouseEventArgs e)
    {
        try
        {
            // 转换坐标,使之相对于列头单元格
            Point cellRelativeCoords = new Point(e.X + this.DataGridView.GetCellDisplayRectangle(e.ColumnIndex, -1, true).Left, e.Y);

            // 创建一个比可视按钮大的点击检测区域
            Rectangle largerClickArea = new Rectangle(
                dropdownButtonRect.Left, // 扩大点击区域
                dropdownButtonRect.Top,  // 扩大点击区域
                dropdownButtonRect.Width, // 扩大点击区域
                dropdownButtonRect.Height  // 扩大点击区域
            );

            Rectangle headcellArea = this.DataGridView.GetCellDisplayRectangle(this.ColumnIndex, this.RowIndex, false);

            if (largerClickArea.Contains(cellRelativeCoords))
            {
                return;
            }

            if (filterMenu.Items.Count > 1)
            {
                if (headcellArea.Contains(cellRelativeCoords))
                {
                    return;
                }
            }
        }
        catch (Exception ex)
        {
            LogHelper.Error(ex.Message + ";" + ex.StackTrace);
        }
        base.OnMouseUp(e);
    }

    private void FilterMenu_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
    {
        try
        {
            if (e.ClickedItem is ToolStripSeparator)
                return;
            ToolStripMenuItem clickedItem = (ToolStripMenuItem)e.ClickedItem;
            string filterValue = clickedItem.Text;

            // Handle the "All" option
            if (filterValue == "All")
            {
                // If "All" is clicked, clear all filters and uncheck all other items
                selectedFilters.Clear();
                dropdownOpen = false;
                foreach (ToolStripMenuItem item in filterMenu.Items.OfType<ToolStripMenuItem>())
                {
                    item.Checked = false;
                }
                clickedItem.Checked = true; // Check the "All" item
            }
            else
            {
                // This is a regular filter item
                clickedItem.Checked = !clickedItem.Checked; // Toggle the checked state

                // Update the selected filters based on the item's checked state
                if (clickedItem.Checked)
                {
                    dropdownOpen = true;
                    selectedFilters.Add(filterValue);
                    // Uncheck the "All" item if any other item is checked
                    ToolStripMenuItem allItem = (ToolStripMenuItem)filterMenu.Items[0];
                    allItem.Checked = false;
                }
                else
                {
                    selectedFilters.Remove(filterValue);
                }
            }


            ApplyFilter();
            clickedItem.Invalidate();
        }
        catch (Exception ex)
        {
            LogHelper.Error(ex.Message + ";" + ex.StackTrace);
        }
    }

    private void FilterMenu_Closing(object sender, ToolStripDropDownClosingEventArgs e)
    {
        try
        {
            // Prevent the menu from closing when an item is clicked.
            if (e.CloseReason == ToolStripDropDownCloseReason.ItemClicked)
            {
                e.Cancel = true;
                (sender as ToolStripDropDownMenu).Invalidate();
            }
        }
        catch (Exception ex)
        {
            LogHelper.Error(ex.Message + ";" + ex.StackTrace);
        }

    }

    private void ShowFilterMenu()
    {
        try
        {
            InitializeFilterMenu();
            filterMenu.Show(this.DataGridView, this.DataGridView.GetCellDisplayRectangle(OwningColumn.Index, -1, true).Location);
        }
        catch (Exception ex)
        {
            LogHelper.Error(ex.Message + ";" + ex.StackTrace);
        }

    }

    private void InitializeFilterMenu()
    {
        try
        {
            filterMenu.Items.Clear();
            foreach (DataGridViewRow row in this.DataGridView.Rows)
            {
                string value = row.Cells[this.ColumnIndex].Value.ToString();
                if (!allFilterValues.Contains(value))
                {
                    allFilterValues.Add(value);
                }
            }
            allFilterValues.Sort();
            //allFilterValues = GetUniqueValuesForColumn(this.OwningColumn.DataPropertyName);
            ToolStripMenuItem allItem = new ToolStripMenuItem("All")
            {
                CheckOnClick = false,
                Checked = selectedFilters.Count == 0
            };

            filterMenu.Items.Add(allItem);
            filterMenu.Items.Add(new ToolStripSeparator()); // Add a separator
            foreach (string value in allFilterValues)
            {
                ToolStripMenuItem item = new ToolStripMenuItem(value)
                {
                    CheckOnClick = false,
                    Checked = selectedFilters.Contains(value)
                };
                filterMenu.Items.Add(item);
            }
        }
        catch (Exception ex)
        {
            LogHelper.Error(ex.Message + ";" + ex.StackTrace);
        }
    }



    private void ApplyFilter()
    {
        try
        {
            //if (this.DataGridView?.DataSource is BindingSource bindingSource)
            //{
            //    string filterString = CreateFilterString(selectedFilters);
            //    bindingSource.Filter = filterString;
            //}
            //else
            //{
            //    // Debug.WriteLine("dfsdf");

            //}

            //if (listAllRow.Count == 0)
            //{
            //    foreach (DataGridViewRow row in this.DataGridView.Rows)
            //    {
            //        listAllRow.Add(row);
            //    }
            //}

            //check has another filter
            Dictionary<FilterableHeaderCell, HashSet<string>> dicHeaderCellFilter = new Dictionary<FilterableHeaderCell, HashSet<string>>();
            foreach (DataGridViewColumn column in this.DataGridView.Columns)
            {
                var headerCell = column.HeaderCell;
                if (headerCell is FilterableHeaderCell)
                {
                    dicHeaderCellFilter[(FilterableHeaderCell)headerCell] = ((FilterableHeaderCell)headerCell).selectedFilters;
                }
            }

            this.DataGridView.Rows.Clear();
            List<DataGridViewRow> baseRows = new List<DataGridViewRow>();
            foreach (DataGridViewRow row in listAllRow)
            {
                baseRows.Add(row);
            }

            foreach (var kvp in dicHeaderCellFilter)
            {
                FilterableHeaderCell headerCell = kvp.Key;
                HashSet<string> filter = kvp.Value;

                List<DataGridViewRow> listRemovedRow = new List<DataGridViewRow>();
                foreach (DataGridViewRow row in baseRows)
                {
                    string cellValue = row.Cells[headerCell.ColumnIndex].Value.ToString();
                    if (filter.Count > 0 && !filter.Contains(cellValue))
                    {
                        listRemovedRow.Add(row);
                    }
                }

                foreach (DataGridViewRow row in listRemovedRow)
                {
                    baseRows.Remove(row);
                }
            }

            foreach (DataGridViewRow row in baseRows)
            {
                this.DataGridView.Rows.Add(row);
            }
        }
        catch (Exception ex)
        {
            LogHelper.Error(ex.Message + ";" + ex.StackTrace);
        }
    }

    private string CreateFilterString(HashSet<string> filters)
    {
        try
        {
            if (filters.Count == 0) return string.Empty;

            var filterParts = filters.Select(f => string.Format("[{0}] = '{1}'", this.OwningColumn.DataPropertyName, f.Replace("'", "''")));
            return string.Join(" OR ", filterParts);
        }
        catch (Exception ex)
        {
            LogHelper.Error(ex.Message + ";" + ex.StackTrace);
        }
        return "";
    }

    private List<string> GetUniqueValuesForColumn(string dataPropertyName)
    {
        var uniqueValues = new HashSet<string>();
        try
        {
            foreach (DataGridViewRow row in this.DataGridView.Rows)
            {
                if (!row.IsNewRow)
                {
                    var value = row.Cells[dataPropertyName].Value?.ToString() ?? string.Empty;
                    uniqueValues.Add(value);
                }
            }
        }
        catch (Exception ex)
        {
            LogHelper.Error(ex.Message + ";" + ex.StackTrace);
        }
        return uniqueValues.ToList();
    }
}
#endregion
  • 调用方式
#region 设置表头
List<DataGridViewColumn> listFilterColumns = new List<DataGridViewColumn>();
listFilterColumns.Add(clmSubWo);
listFilterColumns.Add(clmMaterialState);
listFilterColumns.Add(clmMaterialPartNumber);
listFilterColumns.Add(clmEquPartNumber);
listFilterColumns.Add(clmEquState);
foreach (DataGridViewColumn column in listFilterColumns)
{
    column.HeaderCell = new FilterableHeaderCell(column.HeaderText);
}
#endregion
    
#region 初始化数据源
private void RestHeaderCell(DataGridView dataGridView)
{
    try
    {
        foreach (DataGridViewColumn column in listFilterColumns)
        {
            if (dataGridView.Columns.Contains(column))
            {
                ((FilterableHeaderCell)column.HeaderCell).Rest();
            }
        }
    }
    catch (Exception ex)
    {
        LogHelper.Error(ex.Message);
    }
}
#endregion
    
//执行初始化
RestHeaderCell(gridMaterialBinNumber);
  • 效果
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值