Click here to Skip to main content
15,895,667 members
Home / Discussions / C#
   

C#

 
QuestionSetup Problem &Question Pin
Said Ali Jalali13-Jan-10 7:23
Said Ali Jalali13-Jan-10 7:23 
AnswerRe: Setup Problem &Question Pin
SajjadZare13-Jan-10 9:18
SajjadZare13-Jan-10 9:18 
QuestionProlog Pin
farokhian13-Jan-10 6:15
farokhian13-Jan-10 6:15 
AnswerRe: Prolog Pin
Ennis Ray Lynch, Jr.13-Jan-10 6:51
Ennis Ray Lynch, Jr.13-Jan-10 6:51 
GeneralRe: Prolog Pin
farokhian13-Jan-10 6:59
farokhian13-Jan-10 6:59 
AnswerRe: Prolog Pin
Richard MacCutchan13-Jan-10 7:00
mveRichard MacCutchan13-Jan-10 7:00 
QuestionSetDataSourceLocation to CrystalReport Pin
lordofcsharp13-Jan-10 3:59
lordofcsharp13-Jan-10 3:59 
QuestionStrange problems with DataGridView with Panels in the heading [modified] Pin
arnold_w13-Jan-10 3:36
arnold_w13-Jan-10 3:36 
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()
  {
    // Determine width of label
    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;
      }
      // Set the correct vertical position of the panel. Set the horisontal position
      // to something outside of the dataGridView.
      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
      {
        // Maybe check maximum of size of header text and panel size
        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
    { // Another column was clicked. Reset this column's sorting.
      sortType = SortType.None;
    }
  }


  private void dataGridView_Paint(object sender, PaintEventArgs e)
  {
    Rectangle r1 = dataGridView.GetCellDisplayRectangle(columnIndex, -1, true);
    if (10 <= r1.Width)
    { // We need at least 10 pixel to draw the arrow
      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)
    { // We need to move the column
      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;
    }

    // Determine new panel width
    int newPanelWidth = uncutPanelSize.Width;
    if (0 < cutFromLeft)
    {
      newPanelWidth -= cutFromLeft;
    }
    if (0 < cutFromRight)
    {
      newPanelWidth -= cutFromRight;
    }
    panel.Width = newPanelWidth;

    // Move around components appropriately
    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;
    }

    // Do we need to move the panel?
    if (hiddenToTheLeft == 0)
    {
      panel.Location = new Point(r1.X + 1, panel.Location.Y);
    }
    else if (0 < hiddenToTheLeft)
    { // Place the panel to the right of the cell in the upper leftmost corner
      panel.Location = new Point(dataGridView.GetCellDisplayRectangle(-1, -1, true).Width + 1, panel.Location.Y);
    }

    // Do we need to cut the panel?
    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

AnswerRe: Strange problems with DataGridView with Panels in the heading Pin
arnold_w13-Jan-10 4:48
arnold_w13-Jan-10 4:48 
QuestionHow to save a webpage to a jpeg Pin
kozu13-Jan-10 3:35
kozu13-Jan-10 3:35 
AnswerRe: How to save a webpage to a jpeg Pin
Nuri Ismail13-Jan-10 3:49
Nuri Ismail13-Jan-10 3:49 
GeneralRe: How to save a webpage to a jpeg Pin
kozu13-Jan-10 6:45
kozu13-Jan-10 6:45 
GeneralRe: How to save a webpage to a jpeg Pin
Luc Pattyn13-Jan-10 9:25
sitebuilderLuc Pattyn13-Jan-10 9:25 
GeneralRe: How to save a webpage to a jpeg Pin
Nuri Ismail13-Jan-10 20:58
Nuri Ismail13-Jan-10 20:58 
Questionthird party components Pin
djsproject13-Jan-10 3:33
djsproject13-Jan-10 3:33 
AnswerRe: third party components Pin
Richard MacCutchan13-Jan-10 3:38
mveRichard MacCutchan13-Jan-10 3:38 
QuestionRe: third party components Pin
djsproject13-Jan-10 3:42
djsproject13-Jan-10 3:42 
AnswerRe: third party components Pin
Richard MacCutchan13-Jan-10 4:26
mveRichard MacCutchan13-Jan-10 4:26 
AnswerRe: third party components Pin
Ashfield13-Jan-10 5:07
Ashfield13-Jan-10 5:07 
AnswerRe: third party components Pin
Mirko198013-Jan-10 22:31
Mirko198013-Jan-10 22:31 
Questionneed suggestion for the code Pin
abcurl13-Jan-10 3:25
abcurl13-Jan-10 3:25 
AnswerRe: need suggestion for the code Pin
Richard MacCutchan13-Jan-10 3:41
mveRichard MacCutchan13-Jan-10 3:41 
GeneralRe: need suggestion for the code Pin
abcurl13-Jan-10 3:43
abcurl13-Jan-10 3:43 
GeneralRe: need suggestion for the code Pin
Richard MacCutchan13-Jan-10 4:29
mveRichard MacCutchan13-Jan-10 4:29 
AnswerRe: need suggestion for the code Pin
David Skelly13-Jan-10 4:23
David Skelly13-Jan-10 4:23 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.