/// <summary> /// Adjusts the column width relative to the given <see cref="MultiHeaderCell"/> based on its width. /// </summary> /// <param name="headerCell">A <see cref="MultiHeaderCell"/> object.</param> private void AdjustColumnsWidth(MultiHeaderCell headerCell) { if (headerCell == null || !AutoSizeColumnsBasedOnAdditionalHeadersContent || AutoSizeColumnsMode == DataGridViewAutoSizeColumnsMode.None) { return; } // Calculate the total width of the base columns the headerCell spans var spanningInfo = MultiHeaderCellsSpanningInfo.GetHeaderCellSpanningInfo(this, headerCell); // Nothing to do if the spanning columns width already accomodates space for the computed headerCell's width if (spanningInfo.TotalSpanningWidth >= headerCell.CellSize.Width) { return; } // Re-adjust grid's columns widths spanned by the headerCell int remainder; int proportionalWidthToIncrease = Math.DivRem(headerCell.CellSize.Width - spanningInfo.VisibleWidth, headerCell.ColumnSpan, out remainder); if (remainder > 0) { proportionalWidthToIncrease++; } int lastColumnIndex = headerCell.GetLastBaseColumnIndexFromSpan(Columns.Count); for (int idx = headerCell.ColumnIndex; idx <= lastColumnIndex; idx++) { DataGridViewColumn spanningColumn = Columns[idx]; int newWidth = spanningColumn.Width + proportionalWidthToIncrease; _skipColumnWidthsAdjustment = true; spanningColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.None; spanningColumn.Width = newWidth; _skipColumnWidthsAdjustment = false; } }
/// <summary> /// Raises the <see cref="Control.Paint"/> event. /// </summary> /// <param name="e">A <see cref="PaintEventArgs"/> that contains the event data.</param> protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); // Enforce that the alignment of the original header text is at the bottom, so the other header rows can be drawn correctly. ColumnHeadersDefaultCellStyle.Alignment = BaseColumnHeadersTextAlignment.ToBottomAlignment(); // Get the total height for header rows ColumnHeadersHeight = GetTotalHeaderRowsHeight(); if (_multiHeaderRowsList == null || _multiHeaderRowsList.Count == 0) { return; } // Set other properties and process each additional row. var rowsQuantity = _multiHeaderRowsList.Count; var foregroundBrush = new SolidBrush(ColumnHeadersDefaultCellStyle.ForeColor); var backgroundBrush = new SolidBrush(ColumnHeadersDefaultCellStyle.BackColor); int accumulatedRowHeights = 0; for (int rowIndex = 0; rowIndex < rowsQuantity; rowIndex++) { int reversedRowIndex = ReverseMultiHeaderRowOrder ? rowsQuantity - rowIndex - 1 : rowIndex; var headerRow = _multiHeaderRowsList[reversedRowIndex]; var headerRowHeight = UseFixedColumnHeadersHeight ? FixedColumnHeadersHeight : headerRow.Height; foreach (var headerCell in headerRow.Where(headerCell => !headerCell.InSpan)) { // Calculate the information for the cells being spanned by the currently processed headerCell. var spanningInfo = MultiHeaderCellsSpanningInfo.GetHeaderCellSpanningInfo(this, headerCell); // If the spanning columns are not fully visible, then skip. if (spanningInfo.VisibleArea == Rectangle.Empty) { continue; } // Compute the rectangle areas to manually draw the additional header var headerAreaWithSeparatorsRectangle = new Rectangle( spanningInfo.VisibleArea.Left, spanningInfo.VisibleArea.Top + accumulatedRowHeights, spanningInfo.VisibleWidth, headerRowHeight); e.Graphics.SetClip(headerAreaWithSeparatorsRectangle); var headerDrawableAreaRectangle = new Rectangle( headerAreaWithSeparatorsRectangle.Left - spanningInfo.LeftOverflowingWidth, headerAreaWithSeparatorsRectangle.Top, spanningInfo.TotalSpanningWidth - Math.Max(ColumnHeadersSeparatorWidth, spanningInfo.RightDividerWidth + 1), headerAreaWithSeparatorsRectangle.Height - ColumnHeadersSeparatorWidth); var topPadding = UseColumnPaddings ? headerCell.Style.Padding.Top : 0; var bottomPadding = UseColumnPaddings ? headerCell.Style.Padding.Bottom : 0; var leftPadding = UseColumnPaddings ? headerCell.Style.Padding.Left : 0; var rightPadding = UseColumnPaddings ? headerCell.Style.Padding.Right : 0; var textAreaRectangle = new Rectangle( headerDrawableAreaRectangle.Left + leftPadding, headerDrawableAreaRectangle.Top + topPadding, headerDrawableAreaRectangle.Width - leftPadding - rightPadding, headerDrawableAreaRectangle.Height - bottomPadding - topPadding); // Draw area with separators backgroundBrush.Color = ColumnHeadersSeparatorColor; e.Graphics.FillRectangle(backgroundBrush, headerAreaWithSeparatorsRectangle); // Draw header area with its background color on top of the area with separators to emulate the separators backgroundBrush.Color = headerCell.Style.BackColor; e.Graphics.FillRectangle(backgroundBrush, headerDrawableAreaRectangle); // Draw the header text foregroundBrush.Color = headerCell.Style.ForeColor.IsEmpty ? ColumnHeadersDefaultCellStyle.ForeColor : headerCell.Style.ForeColor; var headerFont = headerCell.Style.Font ?? ColumnHeadersDefaultCellStyle.Font; e.Graphics.DrawString(headerCell.Text, headerFont, foregroundBrush, textAreaRectangle, headerCell.Style.Alignment.ToStringFormat()); } accumulatedRowHeights += headerRowHeight; } foregroundBrush.Dispose(); backgroundBrush.Dispose(); }