I want to be able to add a Panel with controls onto the headings of a DataGridView. I have come pretty far, but now I am stuck with two issues. The code is rather complex with lots of events so in order to be able to help me with these issues, you probably have to reproduce the problem and see them for yourself. Unfortunately, this means I have to include lots of code in this post and please accept my apologies for doing that. The issues I am asking for help with are the following:
1. If you sort the last column, the last column scrolls a little bit for some reason.
2. If I don't add any rows to the table and scroll horizontically, the Panels in the headings don't move.
public partial class Form1 : Form
{
private Table table;
public Form1()
{
InitializeComponent();
this.Load += new EventHandler(Form1_Load);
table = new Table(new string[] { "Column 1", "Column 2", "Column 3" });
table.Location = new Point(0, 0);
table.Size = new Size(300, 300);
table.addRows(new string[][] {
new string[] { "Row 00, Column 0", "Row 00, Column 1", "Row 00, Column 2" },
new string[] { "Row 01, Column 0", "Row 01, Column 1", "Row 01, Column 2" },
new string[] { "Row 02, Column 0", "Row 02, Column 1", "Row 02, Column 2" },
new string[] { "Row 03, Column 0", "Row 03, Column 1", "Row 03, Column 2" },
new string[] { "Row 04, Column 0", "Row 04, Column 1", "Row 04, Column 2" },
new string[] { "Row 05, Column 0", "Row 05, Column 1", "Row 05, Column 2" },
new string[] { "Row 06, Column 0", "Row 06, Column 1", "Row 06, Column 2" },
new string[] { "Row 07, Column 0", "Row 07, Column 1", "Row 07, Column 2" },
new string[] { "Row 08, Column 0", "Row 08, Column 1", "Row 08, Column 2" },
new string[] { "Row 09, Column 0", "Row 09, Column 1", "Row 09, Column 2" },
new string[] { "Row 10, Column 0", "Row 10, Column 1", "Row 10, Column 2" },
new string[] { "Row 11, Column 0", "Row 11, Column 1", "Row 11, Column 2" },
new string[] { "Row 12, Column 0", "Row 12, Column 1", "Row 12, Column 2" }
});
this.Controls.Add(table);
}
private void Form1_Load(object sender, System.EventArgs e)
{
table.parentFormLoad();
}
}
public class Table : Control
{
private DataGridView dataGridView = new DataGridView();
private DataTable dataTable = new DataTable();
private DataColumn[] dataColumns;
public Table(string[] columnHeadings)
{
this.SizeChanged += new EventHandler(Control_SizeChanged);
dataGridView.AllowUserToAddRows = false;
dataGridView.AllowUserToDeleteRows = false;
dataGridView.AllowUserToOrderColumns = false;
dataGridView.Dock = DockStyle.Fill;
dataGridView.DataSource = dataTable;
if (columnHeadings != null)
{
dataColumns = new DataColumn[columnHeadings.Length];
for (int i = 0; i < columnHeadings.Length; i++)
{
dataColumns[i] = new GenericDataColumn(i, columnHeadings[i], new MinMaxDatePanel(), dataGridView);
dataTable.Columns.Add(dataColumns[i]);
}
}
this.Controls.AddRange(new Control[] { dataGridView });
}
public void parentFormLoad()
{
dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
dataGridView.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.TopCenter;
int maxColumnHeight = dataGridView.ColumnHeadersHeight;
for (int i = 0; i < dataColumns.Length; i++)
{
if (maxColumnHeight < ((GenericDataColumn)dataColumns[i]).recommendedSize.Height)
{
maxColumnHeight = ((GenericDataColumn)dataColumns[i]).recommendedSize.Height;
}
dataGridView.Columns[i].Width = ((GenericDataColumn)dataColumns[i]).recommendedSize.Width;
((GenericDataColumn)dataColumns[i]).parentDataGridViewFinishedLoading();
}
dataGridView.ColumnHeadersHeight = maxColumnHeight;
}
private void Control_SizeChanged(object sender, EventArgs e)
{
dataGridView.Size = this.Size;
}
public void addRows(string[][] cellValues)
{
for (int i = 0; i < cellValues.Length; i++)
{
dataTable.Rows.Add(cellValues[i]);
}
}
}
public class MinMaxDatePanel : Panel
{
private const int STANDARD_COLUMN_HEIGHT = 23;
private const int DATEPICKER_WIDTH = 130;
private int LABEL_WIDTH;
private Label minDateLabel;
private Label maxDateLabel;
private DateTimePicker minDatePicker;
private DateTimePicker maxDatePicker;
public MinMaxDatePanel()
{
Label dummyLabel = new Label();
dummyLabel.Text = "Start Date:";
dummyLabel.Visible = false;
dummyLabel.AutoSize = true;
this.Controls.Add(dummyLabel);
LABEL_WIDTH = dummyLabel.Width;
this.Controls.Remove(dummyLabel);
this.minDatePicker = new DateTimePicker();
this.maxDatePicker = new DateTimePicker();
this.minDatePicker.Width = DATEPICKER_WIDTH;
this.maxDatePicker.Width = DATEPICKER_WIDTH;
this.minDatePicker.Location = new Point(LABEL_WIDTH, 0);
this.maxDatePicker.Location = new Point(minDatePicker.Location.X, STANDARD_COLUMN_HEIGHT);
this.minDatePicker.ShowCheckBox = true;
this.maxDatePicker.ShowCheckBox = true;
this.minDatePicker.MinDate = new DateTime(2005, 01, 01);
this.maxDatePicker.MinDate = new DateTime(2005, 01, 01);
this.minDatePicker.MaxDate = new DateTime(2099, 12, 31);
this.maxDatePicker.MaxDate = new DateTime(2099, 12, 31);
this.minDatePicker.Value = this.minDatePicker.MinDate;
this.maxDatePicker.Value = this.maxDatePicker.MaxDate;
this.minDatePicker.Checked = false;
this.maxDatePicker.Checked = false;
this.minDateLabel = new Label();
this.maxDateLabel = new Label();
this.minDateLabel.Text = "Start Date:";
this.maxDateLabel.Text = "End Date:";
this.minDateLabel.Width = LABEL_WIDTH;
this.maxDateLabel.Width = LABEL_WIDTH;
this.minDateLabel.Location = new Point(0, minDatePicker.Location.Y + 2);
this.maxDateLabel.Location = new Point(0, maxDatePicker.Location.Y + 2);
this.Size = new Size(this.minDatePicker.Location.X + this.minDatePicker.Width + 3, 2 * STANDARD_COLUMN_HEIGHT);
this.Controls.AddRange(new Control[] {
minDateLabel, maxDateLabel,
minDatePicker, maxDatePicker});
}
}
public class GenericDataColumn : DataColumn
{
private Size STANDARD_COLUMN_SIZE = new Size(120, 23);
private int columnIndex;
private Size uncutPanelSize = new Size(0, 0);
private Point[] initialControlLocations;
private DataGridView dataGridView;
private Panel panel;
private SortType sortType = SortType.None;
public GenericDataColumn(int columnIndex,
string columnName,
Panel panel,
DataGridView dataGridView)
{
this.columnIndex = columnIndex;
this.ColumnName = columnName;
this.dataGridView = dataGridView;
this.panel = panel;
if (panel != null)
{
this.uncutPanelSize = panel.Size;
this.initialControlLocations = new Point[panel.Controls.Count];
for (int i = 0; i < panel.Controls.Count; i++)
{
initialControlLocations[i] = panel.Controls[i].Location;
}
this.panel.Location = new Point(Int32.MaxValue, STANDARD_COLUMN_SIZE.Height + 1);
}
dataGridView.Controls.Add(this.panel);
}
public Size recommendedSize
{
get
{
if (panel == null)
{
return STANDARD_COLUMN_SIZE;
}
else
{
return new Size(uncutPanelSize.Width + 2, STANDARD_COLUMN_SIZE.Height + uncutPanelSize.Height + 1);
}
}
}
public void parentDataGridViewFinishedLoading()
{
dataGridView.Paint += new PaintEventHandler(dataGridView_Paint);
dataGridView.Resize += new EventHandler(dataGridView_Resize);
dataGridView.Scroll += new ScrollEventHandler(dataGridView_Scroll);
dataGridView.ColumnWidthChanged += new DataGridViewColumnEventHandler(dataGridView_ColumnWidthChanged);
dataGridView.RowPostPaint += new DataGridViewRowPostPaintEventHandler(dataGridView_RowPostPaint);
dataGridView.ColumnHeaderMouseClick += new DataGridViewCellMouseEventHandler(dataGridView_ColumnHeaderMouseClick);
updatePanelGeograpy();
}
private enum SortType
{
Ascending,
Descending,
None
}
private void dataGridView_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
if (e.ColumnIndex == columnIndex)
{
if (sortType == SortType.Ascending)
{
sortType = SortType.Descending;
}
else
{
sortType = SortType.Ascending;
}
}
else
{
sortType = SortType.None;
}
}
private void dataGridView_Paint(object sender, PaintEventArgs e)
{
Rectangle r1 = dataGridView.GetCellDisplayRectangle(columnIndex, -1, true);
if (10 <= r1.Width)
{
if (sortType == SortType.Ascending)
{
drawSortArrow(e.Graphics, new Point(r1.X + r1.Width - 10, r1.Y + 5), true);
}
else if (sortType == SortType.Descending)
{
drawSortArrow(e.Graphics, new Point(r1.X + r1.Width - 10, r1.Y + 5), false);
}
}
r1.X += 1;
r1.Y = STANDARD_COLUMN_SIZE.Height + 1;
r1.Width -= 2;
r1.Height = recommendedSize.Height - STANDARD_COLUMN_SIZE.Height - 1;
e.Graphics.FillRectangle(new SolidBrush(dataGridView.ColumnHeadersDefaultCellStyle.BackColor), r1);
}
private void dataGridView_Scroll(object sender, ScrollEventArgs e)
{
dataGridView.Invalidate();
}
private void dataGridView_RowPostPaint(Object sender, DataGridViewRowPostPaintEventArgs e)
{
if (e.IsFirstDisplayedRow)
{
updatePanelGeograpy();
}
}
private void dataGridView_Resize(object sender, EventArgs e)
{
updatePanelGeograpy();
}
private void dataGridView_ColumnWidthChanged(object sender, DataGridViewColumnEventArgs e)
{
if (e.Column.DisplayIndex == columnIndex - 1)
{
updatePanelGeograpy();
}
else if (e.Column.DisplayIndex == columnIndex)
{
uncutPanelSize.Width = e.Column.Width - 2;
panel.Width = uncutPanelSize.Width;
updatePanelGeograpy();
}
}
private void cutPanel(int cutFromLeft, int cutFromRight)
{
if ((panel == null) || (panel.Controls == null) || (panel.Controls.Count <= 0))
{
return;
}
int newPanelWidth = uncutPanelSize.Width;
if (0 < cutFromLeft)
{
newPanelWidth -= cutFromLeft;
}
if (0 < cutFromRight)
{
newPanelWidth -= cutFromRight;
}
panel.Width = newPanelWidth;
if (0 <= cutFromLeft)
{
for (int i = 0; i < panel.Controls.Count; i++)
{
panel.Controls[i].Location = new Point(initialControlLocations[i].X - cutFromLeft, initialControlLocations[i].Y);
}
}
}
private void updatePanelGeograpy()
{
Rectangle r1 = dataGridView.GetCellDisplayRectangle(columnIndex, -1, true);
Rectangle r2 = dataGridView.GetCellDisplayRectangle(columnIndex, -1, false);
int columnWidth = dataGridView.Columns[columnIndex].Width;
int hiddenToTheRight = r2.Width - r1.Width;
int hiddenToTheLeft = 0;
if (r1.Width + hiddenToTheRight < columnWidth)
{
hiddenToTheLeft = columnWidth - r1.Width - hiddenToTheRight;
}
if (hiddenToTheLeft == 0)
{
panel.Location = new Point(r1.X + 1, panel.Location.Y);
}
else if (0 < hiddenToTheLeft)
{
panel.Location = new Point(dataGridView.GetCellDisplayRectangle(-1, -1, true).Width + 1, panel.Location.Y);
}
cutPanel(hiddenToTheLeft, hiddenToTheRight);
}
private void drawSortArrow(Graphics graphics, Point location, bool arrowPointingUpwards)
{
Color grayColorToUse = Color.FromArgb(132, 130, 132);
if (arrowPointingUpwards)
{
graphics.DrawLine(new Pen(Color.White, 1), new Point(location.X + 0, location.Y + 6), new Point(location.X + 7, location.Y + 6));
graphics.DrawLine(new Pen(Color.White, 1), new Point(location.X + 4, location.Y + 0), new Point(location.X + 4, location.Y + 1));
graphics.DrawLine(new Pen(Color.White, 1), new Point(location.X + 5, location.Y + 1), new Point(location.X + 5, location.Y + 3));
graphics.DrawLine(new Pen(Color.White, 1), new Point(location.X + 6, location.Y + 3), new Point(location.X + 6, location.Y + 4));
graphics.DrawLine(new Pen(Color.White, 1), new Point(location.X + 6, location.Y + 5), new Point(location.X + 7, location.Y + 5));
graphics.DrawLine(new Pen(grayColorToUse, 1), new Point(location.X + 3, location.Y + 0), new Point(location.X + 3, location.Y + 1));
graphics.DrawLine(new Pen(grayColorToUse, 1), new Point(location.X + 2, location.Y + 1), new Point(location.X + 2, location.Y + 3));
graphics.DrawLine(new Pen(grayColorToUse, 1), new Point(location.X + 1, location.Y + 3), new Point(location.X + 1, location.Y + 4));
graphics.DrawLine(new Pen(grayColorToUse, 1), new Point(location.X + 0, location.Y + 5), new Point(location.X + 1, location.Y + 5));
}
else
{
graphics.DrawLine(new Pen(Color.White, 1), new Point(location.X + 0, location.Y + 0), new Point(location.X + 7, location.Y + 0));
graphics.DrawLine(new Pen(Color.White, 1), new Point(location.X + 6, location.Y + 1), new Point(location.X + 7, location.Y + 1));
graphics.DrawLine(new Pen(Color.White, 1), new Point(location.X + 6, location.Y + 2), new Point(location.X + 6, location.Y + 3));
graphics.DrawLine(new Pen(Color.White, 1), new Point(location.X + 5, location.Y + 3), new Point(location.X + 5, location.Y + 5));
graphics.DrawLine(new Pen(Color.White, 1), new Point(location.X + 4, location.Y + 5), new Point(location.X + 4, location.Y + 6));
graphics.DrawLine(new Pen(grayColorToUse, 1), new Point(location.X + 0, location.Y + 1), new Point(location.X + 1, location.Y + 1));
graphics.DrawLine(new Pen(grayColorToUse, 1), new Point(location.X + 1, location.Y + 2), new Point(location.X + 1, location.Y + 3));
graphics.DrawLine(new Pen(grayColorToUse, 1), new Point(location.X + 2, location.Y + 3), new Point(location.X + 2, location.Y + 5));
graphics.DrawLine(new Pen(grayColorToUse, 1), new Point(location.X + 3, location.Y + 5), new Point(location.X + 3, location.Y + 6));
}
}
}
modified on Wednesday, January 13, 2010 9:42 AM
|