sticky
Windows Forms Data Controls and Databinding FAQ

Toate mesajele

  • 1.      How do I restrict users from setting focus to a specific cell? 

    By default the DataGridView's navigation model does not have any ability to restrict focus to a specific cell. You can implement your own navigation logic by overriding the appropriate keyboard, navigation and mouse methods such as DataGridView.OnKeyDown, DataGridView.ProcessDataGridViewKey, DataGridView.SetCurrentCellAddressCore, DataGridView.SetSelectedCellCore, DataGridView.OnMouseDown.

    For example, assume you want to restrict users from setting focus on the second column, then you have to derive from the DataGridView class and override the SetCurrentCellAddressCore and SetSelectedCellCore to implement the logic you want, the following sample demonstrates how to do this.

    Code Block

    public partial class Form1 : Form

            {

                public Form1()

                {

                    InitializeComponent();

                }

     

                private void Form1_Load(object sender, EventArgs e)

                {

                    DataTable dt = new DataTable();

                    dt.Columns.Add("c1");

                    dt.Columns.Add("c2");

                    dt.Columns.Add("c3");

                    for (int j = 0; j < 10; j++)

                    {

                        dt.Rows.Add("aaa" + j.ToString(), "bbb");

                    }

     

                    this.myDataGridView1.DataSource = dt;

                    this.myDataGridView1.ColumnToSkip = 1;

                }

            }

     

            public class myDataGridView : DataGridView

            {

                private int columnToSkip = -1;

     

                public int ColumnToSkip

                {

                    get { return columnToSkip; }

                    set { columnToSkip = value; }

                }

     

                protected override bool SetCurrentCellAddressCore(int columnIndex, int rowIndex,

                    bool setAnchorCellAddress, bool validateCurrentCell, bool throughMouseClick)

                {

                    if (columnIndex == this.columnToSkip && this.columnToSkip != -1)

                    {

                        if (this.columnToSkip == this.ColumnCount - 1)

                        {

                            return base.SetCurrentCellAddressCore(0, rowIndex + 1,

                                setAnchorCellAddress, validateCurrentCell, throughMouseClick);

                        }

                        else

                        {

                            if (this.ColumnCount != 0)

                            {

                                return base.SetCurrentCellAddressCore(columnIndex + 1, rowIndex,

                                    setAnchorCellAddress, validateCurrentCell, throughMouseClick);

                            }

                        }

                    }

                    return base.SetCurrentCellAddressCore(columnIndex, rowIndex,

                        setAnchorCellAddress, validateCurrentCell, throughMouseClick);

                }

     

                protected override void SetSelectedCellCore(int columnIndex, int rowIndex, bool selected)

                {

                    if (columnIndex == this.columnToSkip)

                    {

                        if (this.columnToSkip == this.ColumnCount - 1)

                        {

                            base.SetSelectedCellCore(0, rowIndex + 1, selected);

                        }

                        else

                        {

                            if (this.ColumnCount != 0)

                            {

                                base.SetSelectedCellCore(columnIndex + 1, rowIndex, selected);

                            }

                        }

                    }

                    else

                    {

                        base.SetSelectedCellCore(columnIndex, rowIndex, selected);

                    }

                }

            }

     



    Related threads:
    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=316283&SiteID=1

    • Editat de Bruce.Zhou 31 decembrie 2008 09:12 change bookmark
    4 decembrie 2007 03:21
  • 2      How can I show vertical text in the cell?

    To make text show vertically in the cells, you have to handle the CellPainting event to draw the text by yourself with a StringFormatFlags.DirectionVertical flag, the following sample demonstrates how to do this:

          
    Code Block

    private void Form1_Load(object sender, EventArgs e)

            {

                DataTable dt = new DataTable();

                dt.Columns.Add("c1");

                dt.Columns.Add("c2");

                for (int j = 0; j < 10; j++)

                {

                    dt.Rows.Add("aaaaaaaaa", "bbbb");

                }

                this.dataGridView1.DataSource = dt;

     

                for (int j = 0; j < 10; j++)

                {

                    int height = TextRenderer.MeasureText(

                        this.dataGridView1[0, j].Value.ToString(),

                        this.dataGridView1.DefaultCellStyle.Font).Width;

                    this.dataGridView1.Rows[j].Height = height;

                }

     

                this.dataGridView1.CellPainting += new

                     DataGridViewCellPaintingEventHandler(dataGridView1_CellPainting); ;

            }

     

            void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)

            {

                if (e.ColumnIndex == 0 && e.RowIndex > -1 && e.Value != null)

                {

                    e.Paint(e.CellBounds, DataGridViewPaintParts.All

                         & ~DataGridViewPaintParts.ContentForeground);

                    StringFormat sf = new StringFormat();

                    sf.Alignment = StringAlignment.Center;

                    sf.LineAlignment = StringAlignment.Center;

                    sf.FormatFlags = StringFormatFlags.DirectionVertical;

                    e.Graphics.DrawString(e.Value.ToString(), e.CellStyle.Font,

                        new SolidBrush(e.CellStyle.ForeColor), e.CellBounds, sf);

                    e.Handled = true;

                }

            }

     

    Related threads:
    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2351571&SiteID=1

    4 decembrie 2007 03:23
  • 3. How to change the default Sort Mode?


    The default SortMode is DataGridViewColumnSortMode.Automatic, in some cases developers would like to change this  default setting but they dislike looping through the columns to change this setting, like this guy on this thread http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2302617&SiteID=1

    To achieve this, we can derive from the DataGridView class and override its OnColumnAdded method  to change the default setting, something like this

    Code Block


            public

    class mydgv : DataGridView

            {

                protected override void OnColumnAdded(DataGridViewColumnEventArgs e)

                {

                    base.OnColumnAdded(e);

                    e.Column.SortMode = DataGridViewColumnSortMode.NotSortable;

                }

            }

     


    Related threads:

    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2302617&SiteID=1

    • Editat de Bruce.Zhou 31 decembrie 2008 09:14 change bookmark
    4 decembrie 2007 03:36
  • 4. Can I dynamically change the DataGridViewCell type?

    Yes.  For example in this thread http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1924281&SiteID=1
    the OP would like to change the DataGridViewComboBoxCell to DataGridViewTextBoxCell dynamically  based on the value selected, in fact,  the cell type can be changed, just by creating a cell of the type you want and assigning it to the cell which you want to change, something like this

    Code Block

     

            private void Form1_Load(object sender, EventArgs e)

            {

                DataTable dt = new DataTable("b");

                dt.Columns.Add("col");

                dt.Rows.Add("bb1");

                dt.Rows.Add("bb2");

                dt.Rows.Add("bb3");

     

                this.dataGridView1.DataSource = dt;

     

                DataGridViewComboBoxColumn cmb = new DataGridViewComboBoxColumn();

                cmb.Items.Add("111");

                cmb.Items.Add("222");

                cmb.Items.Add("333");

                this.dataGridView1.Columns.Add(cmb);

            }

            private void button1_Click(object sender, EventArgs e)

            {

                DataGridViewTextBoxCell cell = new DataGridViewTextBoxCell();

                cell.Value = "bb1";

                this.dataGridView1[1, 1] = cell;

            }

     

     

    Related threads:
    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1924281&SiteID=1
    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2122903&SiteID=1
    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1358083&SiteID=1

    4 decembrie 2007 03:38
  • 5.  How do I  make the DataGridViewComboBoxColumn show  up as a text box column when not in edit mode?


    This is can be done by setting the DataGridViewComboBoxColumn.DisplayStyle property to DataGridViewComboBoxDisplayStyle.Nothing.

    4 decembrie 2007 03:42
  • 6. How do I show multi-layered column headers?

     

    As this thread http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1378821&SiteID=1 asked, someone would like to make the DataGridView column headers show layered information, something like this

    ---------------------------------------------------------------


                    |   January       |   February      |     March       |

            |  Win  | Loss   |  Win   | Loss   |  Win | Loss    |

    ---------------------------------------------------------------

    Team1       |         |          |         |          |          |         |

    Team2       |         |          |         |          |          |         |

    TeamN       |         |          |         |          |          |         |

    ---------------------------------------------------------------


    To achieve this kind of effect, we should handle the DataGridView.Painting and DataGridView.CellPainting events to custom draw the header style we want, the following sample demonstrates how to do this


    (see next post)

    4 decembrie 2007 03:48
  • Code Block


            private void DgvColumnHeaderMerge_Load(object sender, EventArgs e)

            {

                this.dataGridView1.Columns.Add("JanWin", "Win");

                this.dataGridView1.Columns.Add("JanLoss", "Loss");

                this.dataGridView1.Columns.Add("FebWin", "Win");

                this.dataGridView1.Columns.Add("FebLoss", "Loss");

                this.dataGridView1.Columns.Add("MarWin", "Win");

                this.dataGridView1.Columns.Add("MarLoss", "Loss");

     

                for (int j = 0; j < this.dataGridView1.ColumnCount; j++)

                {

                    this.dataGridView1.Columns[j].Width = 45;

                }

                this.dataGridView1.ColumnHeadersHeightSizeMode =

                     DataGridViewColumnHeadersHeightSizeMode.EnableResizing;

                this.dataGridView1.ColumnHeadersHeight =

                            this.dataGridView1.ColumnHeadersHeight * 2;

                this.dataGridView1.ColumnHeadersDefaultCellStyle.Alignment =

                     DataGridViewContentAlignment.BottomCenter;

                this.dataGridView1.CellPainting += new

                     DataGridViewCellPaintingEventHandler(dataGridView1_CellPainting);

                this.dataGridView1.Paint += new PaintEventHandler(dataGridView1_Paint);

     

            }

     

            void dataGridView1_Paint(object sender, PaintEventArgs e)

            {

                string[] monthes = { "January", "February", "March" };

                for (int j = 0; j < 6; )

                {

                    //get the column header cell

                    Rectangle r1 = this.dataGridView1.GetCellDisplayRectangle(j, -1, true);

     

                    r1.X += 1;

                    r1.Y += 1;

                    r1.Width = r1.Width * 2 - 2;

                    r1.Height = r1.Height / 2 - 2;

                    e.Graphics.FillRectangle(new

                       SolidBrush(this.dataGridView1.ColumnHeadersDefaultCellStyle.BackColor), r1);

                    StringFormat format = new StringFormat();

                    format.Alignment = StringAlignment.Center;

                    format.LineAlignment = StringAlignment.Center;

                    e.Graphics.DrawString(monthes[j / 2],

                        this.dataGridView1.ColumnHeadersDefaultCellStyle.Font,

                        new SolidBrush(this.dataGridView1.ColumnHeadersDefaultCellStyle.ForeColor),

                        r1,

                        format);

                    j += 2;

                }

            }

     

            void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)

            {

                if (e.RowIndex == -1 && e.ColumnIndex > -1)

                {

                    e.PaintBackground(e.CellBounds, false);

     

                    Rectangle r2 = e.CellBounds;

                    r2.Y += e.CellBounds.Height / 2;

                    r2.Height = e.CellBounds.Height / 2;

                    e.PaintContent(r2);

                    e.Handled = true;

                }

            }

     

     




    Related threads:
    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1378821&SiteID=1
    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1442065&SiteID=1

    4 decembrie 2007 03:51
  • 7.     How to make multiple controls in a single cell?


    As asked in this thread http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1425662&SiteID=1
    the OP would like to make a Button to show up along with the TextBox. This can be done by creating a UserControl to host the TextBox and Button, add it into the controls collection of the DataGridView, initially make it invisible, then handle the CellBeginEdit event to show the UserControl at the current cell. You also have to handle the Scroll event to adjust the location of the UserControl in case the Scrollbars shows, and handle the CellEndEdit event to change the cell value with the value got from the UserControl. For a full sample please check the thread.

     

    And there is another similar thread where the OP wants to display a Dropdown text editor while editing in the cells.
    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1506454&SiteID=1

    5 decembrie 2007 05:56
  • 8. How to display grouped data in a DataGridView?


             For example, how can I display grouped data as the following graph shows;



    The key point here is to handle the CellPainting event to custom draw the cell to get the style you want, a sample code demonstrates how to do this:


    Code Block

    public class GroupByGrid : DataGridView

            {

     

                protected override void OnCellFormatting(

                   DataGridViewCellFormattingEventArgs args)

                {

                    // Call home to base

                    base.OnCellFormatting(args);

     

                    // First row always displays

                    if (args.RowIndex == 0)

                        return;

     

     

                    if (IsRepeatedCellValue(args.RowIndex, args.ColumnIndex))

                    {

                        args.Value = string.Empty;

                        args.FormattingApplied = true;

                    }

                }

     

                private bool IsRepeatedCellValue(int rowIndex, int colIndex)

                {

                    DataGridViewCell currCell =

                       Rows[rowIndex].Cells[colIndex];

                    DataGridViewCell prevCell =

                       Rows[rowIndex - 1].Cells[colIndex];

     

                    if ((currCell.Value == prevCell.Value) ||

                       (currCell.Value != null && prevCell.Value != null &&

                       currCell.Value.ToString() == prevCell.Value.ToString()))

                    {

                        return true;

                    }

                    else

                    {

                        return false;

                    }

                }

     

                protected override void OnCellPainting(

                   DataGridViewCellPaintingEventArgs args)

                {

                    base.OnCellPainting(args);

     

                    args.AdvancedBorderStyle.Bottom =

                       DataGridViewAdvancedCellBorderStyle.None;

     

                    // Ignore column and row headers and first row

                    if (args.RowIndex < 1 || args.ColumnIndex < 0)

                        return;

     

                    if (IsRepeatedCellValue(args.RowIndex, args.ColumnIndex))

                    {

                        args.AdvancedBorderStyle.Top =

                           DataGridViewAdvancedCellBorderStyle.None;

                    }

                    else

                    {

                        args.AdvancedBorderStyle.Top = AdvancedCellBorderStyle.Top;

                    }

                }

            }

     

     

    5 decembrie 2007 06:18
  • 9. How can I make the Enter key work as Tab key?


          To make the Enter key work as Tab key, we have to derive from the DataGridView control, and there are two cases to think about. One is when the DataGridView is not in edit mode: in this case, we can override the ProcessDataGridViewKey() method to change the navigation logic as we want. The other case is when the DataGridView is in edit mode: in this case, the Enter key is processed in the ProcessDialogKey() method, so we should override this method to write our own logic. The following sample demonstrates how to do this.


     public class MyDataGridView : DataGridView
        {
            protected override bool ProcessDataGridViewKey(KeyEventArgs e)
            {
                if (e.KeyCode == Keys.Enter)
                {
                    this.ProcessTabKey(e.KeyData);
                    return true;
                }
                return base.ProcessDataGridViewKey(e);
            }

            protected override bool ProcessDialogKey(Keys keyData)
            {
                if (keyData == Keys.Enter)
                {
                    this.ProcessTabKey(keyData);
                    return true;
                }
                return base.ProcessDialogKey(keyData);
            }
        }

     

    5 decembrie 2007 06:21
  • 10.    How to restrict the input in the text column to be numeric only?

    When the textbox cell is in edit mode, the EditingControl is shown in the cell, we can restrict the input by handling the TextBox.KeyPress event to filter the keyboard input through the char.IsDigit() method. The following sample demonstrates how to do this.

    Code Block

    public partial class DgvNumberOnlyColumn : Form

            {

                public DgvNumberOnlyColumn()

                {

                    InitializeComponent();

                }

     

                private void DgvNumberOnlyColumn_Load(object sender, EventArgs e)

                {

                    this.dataGridView1.Columns.Add("col1", "col1");

                    this.dataGridView1.Columns.Add("col2", "col2");

                    this.dataGridView1.Rows.Add();

                    this.dataGridView1.EditingControlShowing += new

                         DataGridViewEditingControlShowingEventHandler(

                         dataGridView1_EditingControlShowing);

                }

     

                void dataGridView1_EditingControlShowing(object sender,

                     DataGridViewEditingControlShowingEventArgs e)

                {

                    if (this.dataGridView1.CurrentCell.ColumnIndex == 0)

                    {

                        if (e.Control is TextBox)

                        {

                            TextBox tb = e.Control as TextBox;

                            tb.KeyPress -= new KeyPressEventHandler(tb_KeyPress);

                            tb.KeyPress += new KeyPressEventHandler(tb_KeyPress);

                        }

                    }

                }

     

                void tb_KeyPress(object sender, KeyPressEventArgs e)

                {

                    if (!(char.IsDigit(e.KeyChar)))

                    {

                        Keys key = (Keys)e.KeyChar;

     

                        if (!(key == Keys.Back || key == Keys.Delete))

                        {

                            e.Handled = true;

                        }

                    }

                }

            }

     

     



    Related threads:

    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1757999&SiteID=1

    5 decembrie 2007 06:23
  • 11.    How to make the '\t' character work in the DataGridViewCell when displaying?

    When the DataGridView paints the cell value, the '\t' character is ignored by default. To make the '\t' char work, we can handle the CellPainting event to draw the text by ourselves.

    Code Block


            void
    dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)

            {

                e.Paint(e.CellBounds,

                    DataGridViewPaintParts.All & ~DataGridViewPaintParts.ContentForeground);

                if (e.Value != null)

                {

                    e.Graphics.DrawString(e.Value.ToString(),

                        e.CellStyle.Font,

                        new SolidBrush(e.CellStyle.ForeColor),

                        e.CellBounds.X, e.CellBounds.Y);

                }

                e.Handled = true;

            }

     

     


    Related threads:

    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1898048&SiteID=1

    5 decembrie 2007 06:26
  • 12.    How to make the Enter key and Tab key work in DataGridViewTextBoxCell when in edit mode?

    To make the Enter key and Tab key work in the cell while editing, you have to derive from the DataGridView control, override the ProcessDataGridViewKey method to filter the Tab and Enter key, something like this:

    Code Block


            class
    zxyDataGridView : DataGridView

            {

                protected override bool ProcessDataGridViewKey(KeyEventArgs e)

                {

                    switch (e.KeyCode)

                    {

                        case Keys.Tab:

                            return false;

                        case Keys.Enter:

                            {

                                if (this.EditingControl != null)

                                {

                                    if (this.EditingControl is TextBox)

                                    {

                                        TextBox tx = this.EditingControl as TextBox;

                                        int tmp = tx.SelectionStart;

                                        tx.Text = tx.Text.Insert(tx.SelectionStart,

                                                            Environment.NewLine);

                                        tx.SelectionStart = tmp + Environment.NewLine.Length;

                                        return true;

                                    }

                                }

                            }

                            return false;

                    }

                    return base.ProcessDataGridViewKey(e);

                }

            }

     

     


    To make the Tab key work in edit mode, you have to set the AcceptsTab property to true for the TextBox as well.

           

    Code Block


            void
    dataGridView1_EditingControlShowing(object sender,DataGridViewEditingControlShowingEventArgs e)

            {

                if (e.Control is TextBox)

                {

                    TextBox tb = e.Control as TextBox;

                    tb.AcceptsTab = true;

                }

            }

     

     



    Related threads:
    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1898048&SiteID=1

     

    5 decembrie 2007 06:31
  • 13.    How to make the DataGridView show gridlines in all display areas?

    By default, the DataGridView leaves a gray background if the DataGridView size is larger than the data display area size which is needed. To avoid this, we can derive from the DataGridView and override its OnPaint method to draw extra lines in the non-data area. The following sample demonstrates how to do this.

     

    Code Block

           
            public class
    GridLineDataGridView : DataGridView

            {

                public GridLineDataGridView()

                {

                    this.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;

                }

                protected override void OnPaint(PaintEventArgs e)

                {

                    base.OnPaint(e);

     

                    int rowHeight = this.RowTemplate.Height;

     

                    int h = this.ColumnHeadersHeight + rowHeight * this.RowCount;

                    int imgWidth = this.Width - 2;

                    Rectangle rFrame = new Rectangle(0, 0, imgWidth, rowHeight);

                    Rectangle rFill = new Rectangle(1, 1, imgWidth - 2, rowHeight);

                    Rectangle rowHeader = new Rectangle(2, 2, this.RowHeadersWidth - 3, rowHeight);

     

                    Pen pen = new Pen(this.GridColor, 1);

     

                    Bitmap rowImg = new Bitmap(imgWidth, rowHeight);

                    Graphics g = Graphics.FromImage(rowImg);

                    g.DrawRectangle(pen, rFrame);

                    g.FillRectangle(new SolidBrush(this.DefaultCellStyle.BackColor), rFill);

                    g.FillRectangle(new SolidBrush

                       (this.RowHeadersDefaultCellStyle.BackColor), rowHeader);

     

                    int w = this.RowHeadersWidth - 1;

                    for (int j = 0; j < this.ColumnCount; j++)

                    {

                        g.DrawLine(pen, new Point(w, 0), new Point(w, rowHeight));

                        w += this.Columns[j].Width;

                    }

     

                    int loop = (this.Height - h) / rowHeight;

                    for (int j = 0; j < loop + 1; j++)

                    {

                        e.Graphics.DrawImage(rowImg, 1, h + j * rowHeight);

                    }

                }

            }

     

     



    Related threads:
    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2241055&SiteID=1
    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1947368&SiteID=1

    5 decembrie 2007 06:34
  • 14. How do I prevent a particular cell from being editable?


          The ReadOnly property indicates whether the data displayed by the cell can be edited. You can set ReadOnly for individual cells, or you can make an entire row or column of cells read-only by setting the DataGridViewRow.ReadOnly or DataGridViewColumn.ReadOnly properties. By default, if a cell's parent row or column is set to read-only, the child cells will adopt the same value.

          While you can navigate to a read-only cell, and you can set a read-only cell to be the current cell, the content cannot be modified by the user. Note that the ReadOnly property does not keep the cell from being modified programmatically. Also note that ReadOnly does not affect whether the user can delete rows.

     

    5 decembrie 2007 07:45
  • 15.    How do I disable a cell?

           While a cell can be read-only to prevent it from being editable, the DataGridView does not have built-in support for disabling a cell. Normally the concept of "disabled" means that the user cannot navigate to it and usually has a visual cue that it is disabled.  There isn't any easy way to create the navigational side of disabled, but the visual cue is something that can be done. While none of the built-in cell have a disabled property, the following example extends the DataGridViewButtonCell and implements a visual "disabled" state along with a corresponding disabled property.

    Code Block


            public
    class DataGridViewDisableButtonColumn : DataGridViewButtonColumn

            {

                public DataGridViewDisableButtonColumn()

                {

                    this.CellTemplate = new DataGridViewDisableButtonCell();

                }

            }

     

            public class DataGridViewDisableButtonCell : DataGridViewButtonCell

            {

                private bool enabledValue;

                public bool Enabled

                {

                    get

                    {

                        return enabledValue;

                    }

                    set

                    {

                        enabledValue = value;

                    }

                }

     

                // Override the Clone method so that the Enabled property is copied.

                public override object Clone()

                {

                    DataGridViewDisableButtonCell cell =

                        (DataGridViewDisableButtonCell)base.Clone();

                    cell.Enabled = this.Enabled;

                    return cell;

                }

     

                // By default, enable the button cell.

                public DataGridViewDisableButtonCell()

                {

                    this.enabledValue = true;

                }

     

                protected override void Paint(Graphics graphics,

                    Rectangle clipBounds, Rectangle cellBounds, int rowIndex,

                    DataGridViewElementStates elementState, object value,

                    object formattedValue, string errorText,

                    DataGridViewCellStyle cellStyle,

                    DataGridViewAdvancedBorderStyle advancedBorderStyle,

                    DataGridViewPaintParts paintParts)

                {

                    // The button cell is disabled, so paint the border, 

                    // background, and disabled button for the cell.

                    if (!this.enabledValue)

                    {

                        // Draw the cell background, if specified.

                        if ((paintParts & DataGridViewPaintParts.Background) ==

                            DataGridViewPaintParts.Background)

                        {

                            SolidBrush cellBackground =

                                new SolidBrush(cellStyle.BackColor);

                            graphics.FillRectangle(cellBackground, cellBounds);

                            cellBackground.Dispose();

                        }

     

                        // Draw the cell borders, if specified.

                        if ((paintParts & DataGridViewPaintParts.Border) ==

                            DataGridViewPaintParts.Border)

                        {

                            PaintBorder(graphics, clipBounds, cellBounds, cellStyle,

                                advancedBorderStyle);

                        }

     

                        // Calculate the area in which to draw the button.

                        Rectangle buttonArea = cellBounds;

                        Rectangle buttonAdjustment =

                            this.BorderWidths(advancedBorderStyle);

                        buttonArea.X += buttonAdjustment.X;

                        buttonArea.Y += buttonAdjustment.Y;

                        buttonArea.Height -= buttonAdjustment.Height;

                        buttonArea.Width -= buttonAdjustment.Width;

     

                        // Draw the disabled button.               

                        ButtonRenderer.DrawButton(graphics, buttonArea,

                            PushButtonState.Disabled);

     

                        // Draw the disabled button text.

                        if (this.FormattedValue is String)

                        {

                            TextRenderer.DrawText(graphics,

                                (string)this.FormattedValue,

                                this.DataGridView.Font,

                                buttonArea, SystemColors.GrayText);

                        }

                    }

                    else

                    {

                        // The button cell is enabled, so let the base class

                        // handle the painting.

                        base.Paint(graphics, clipBounds, cellBounds, rowIndex,

                            elementState, value, formattedValue, errorText,

                            cellStyle, advancedBorderStyle, paintParts);

                    }

                }

            }

     

     

     

    5 decembrie 2007 07:47
  • 16. How do I show controls in all cells regardless of edit?


           The DataGridView control only supports displaying an actual control when a cell is in edit mode. The DataGridView control is not designed to display multiple controls or repeat a set of controls per row. The DataGridView control draws a representation of the control when the cell is not being edited. This representation can be a detailed as you want. For example, the DataGridViewButtonCell draws a button regardless of the cell being in edit or not.


           However, you can add controls through DataGridView.Controls.Add() method, and set their location and size to make them hosted in the cells, but showing controls in all cells regardless of editing make no sense.

    5 decembrie 2007 07:51
  • 17. How do I handle the SelectedIndexChanged event?


         Sometimes it is helpful to know when a user has selected an item in the ComboBox editing control. With a ComboBox on your form you would normally handle the SelectedIndexChanged event. With the DataGridViewComboBox you can do the same thing by using the DataGridView.EditingControlShowing event. The following code example demonstrates how to do this. Note that the sample also demonstrates how to keep multiple SelectedIndexChanged events from firing.

     

    Code Block


            private
    void dataGridView1_EditingControlShowing(object sender,

                        DataGridViewEditingControlShowingEventArgs e)

            {

                ComboBox cb = e.Control as ComboBox;

                if (cb != null)

                {

                    // first remove event handler to keep from attaching multiple:

                    cb.SelectedIndexChanged -= new

                    EventHandler(cb_SelectedIndexChanged);

     

                    // now attach the event handler

                    cb.SelectedIndexChanged += new

                    EventHandler(cb_SelectedIndexChanged);

                }

            }

     

            void cb_SelectedIndexChanged(object sender, EventArgs e)

            {

                MessageBox.Show("Selected index changed");

            }

     

     

     


    5 decembrie 2007 07:53
  • 18. How do I show icon and text in the same cell?


         The DataGridView control does not have any built-in support for showing an icon and text in the same cell. Through the different painting customization events, such as the CellPainting event, you can easily display an icon next to the text in the cell.

         The following example extends the DataGridViewTextColumn and cell to paint an image next to the text. The sample uses the DataGridViewCellStyle.Padding property to adjust the text location and overrides the Paint method to paint an icon. This sample can be simplified by handling the CellPainting event and performing similar code.


    Code Block


            public
    class TextAndImageColumn : DataGridViewTextBoxColumn

            {

                private Image imageValue;

                private Size imageSize;

     

                public TextAndImageColumn()

                {

                    this.CellTemplate = new TextAndImageCell();

                }

     

                public override object Clone()

                {

                    TextAndImageColumn c = base.Clone() as TextAndImageColumn;

                    c.imageValue = this.imageValue;

                    c.imageSize = this.imageSize;

                    return c;

                }

     

                public Image Image

                {

                    get { return this.imageValue; }

                    set

                    {

                        if (this.Image != value)

                        {

                            this.imageValue = value;

                            this.imageSize = value.Size;

     

                            if (this.InheritedStyle != null)

                            {

                                Padding inheritedPadding = this.InheritedStyle.Padding;

                                this.DefaultCellStyle.Padding = new Padding(imageSize.Width,

                             inheritedPadding.Top, inheritedPadding.Right,

                             inheritedPadding.Bottom);

                            }

                        }

                    }

                }

                private TextAndImageCell TextAndImageCellTemplate

                {

                    get { return this.CellTemplate as TextAndImageCell; }

                }

                internal Size ImageSize

                {

                    get { return imageSize; }

                }

            }

     



    (see next post )

    5 decembrie 2007 07:59
  • Code Block

     
           public class TextAndImageCell : DataGridViewTextBoxCell

            {

                private Image imageValue;

                private Size imageSize;

     

                public override object Clone()

                {

                    TextAndImageCell c = base.Clone() as TextAndImageCell;

                    c.imageValue = this.imageValue;

                    c.imageSize = this.imageSize;

                    return c;

                }

     

                public Image Image

                {

                    get

                    {

                        if (this.OwningColumn == null ||

                    this.OwningTextAndImageColumn == null)

                        {

     

                            return imageValue;

                        }

                        else if (this.imageValue != null)

                        {

                            return this.imageValue;

                        }

                        else

                        {

                            return this.OwningTextAndImageColumn.Image;

                        }

                    }

                    set

                    {

                        if (this.imageValue != value)

                        {

                            this.imageValue = value;

                            this.imageSize = value.Size;

     

                            Padding inheritedPadding = this.InheritedStyle.Padding;

                            this.Style.Padding = new Padding(imageSize.Width,

                            inheritedPadding.Top, inheritedPadding.Right,

                            inheritedPadding.Bottom);

                        }

                    }

                }

                protected override void Paint(Graphics graphics, Rectangle clipBounds,

                Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState,

                object value, object formattedValue, string errorText,

                DataGridViewCellStyle cellStyle,

                DataGridViewAdvancedBorderStyle advancedBorderStyle,

                DataGridViewPaintParts paintParts)

                {

                    // Paint the base content

                    base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState,

                       value, formattedValue, errorText, cellStyle,

                       advancedBorderStyle, paintParts);

     

                    if (this.Image != null)

                    {

                        // Draw the image clipped to the cell.

                        System.Drawing.Drawing2D.GraphicsContainer container =

                        graphics.BeginContainer();

     

                        graphics.SetClip(cellBounds);

                        graphics.DrawImageUnscaled(this.Image, cellBounds.Location);

     

                        graphics.EndContainer(container);

                    }

                }

     

                private TextAndImageColumn OwningTextAndImageColumn

                {

                    get { return this.OwningColumn as TextAndImageColumn; }

                }

            }

     

    5 decembrie 2007 08:00
  • 19. How do I hide a column?

         Sometimes you will want to display only some of the columns that are available in a DataGridView. For example, you might want to show an employee salary column to users with management credentials while hiding it from other users.

    To hide a column programmatically

    In the DataGridView control, the column's Visible property determines whether the column is displayed.

    To hide a column using the designer

    1) Choose Edit Columns from the control's smart tag.
    2) Select a column from the Selected Columns list.
    3) In the Column Properties grid, set the Visible property to false.

    • Editat de Zhi-Xin Ye 31 decembrie 2008 10:09 test
    5 decembrie 2007 08:03
  • 20. How do I prevent the user from sorting on a column?

    In the DataGridView control, text box columns use automatic sorting by default, while other column types are not sorted automatically. Sometimes you will want to override these defaults.

    In the DataGridView control, the SortMode property value of a column determines its sorting behavior.

    5 decembrie 2007 08:06
  • 21. How do I sort on multiple columns?

          By default the DataGridView control does not provide sorting on multiple columns. Depending upon if the DataGridView is databound or not, you can provide additional support for sorting on multiple columns.

           21.1 Databound DataGridView

          When the DataGridView is databound the datasource can be sorted on multiple columns and the DataGridView will respect that sorting, but the only the first sorted column will display the sort glyph. In addition, the SortedColumn property will only return the first sorted column. 

          Some datasources have built in support for sorting on multiple columns. If your datasource implements IBindingListView and provides support for the Sort property, then using it will provide support for multi-column sorting. To indicate in the grid that multiple columns are sorted on, manually set a column's SortGlyphDirection to properly indicate that the column is sorted. 

          The following example uses a DataTable and sets the default view's Sort property to sort on the second and third columns. The example also demonstrates setting the column's SortGlyphDirection. The example assumes that you have a DataGridView and a BindingSource component on your form:


    Code Block


    DataTable
    dt = new DataTable();

    dt.Columns.Add("C1", typeof(int));

    dt.Columns.Add("C2", typeof(string));

    dt.Columns.Add("C3", typeof(string));

     

    dt.Rows.Add(1, "1", "Test1");

    dt.Rows.Add(2, "2", "Test2");

    dt.Rows.Add(2, "2", "Test1");

    dt.Rows.Add(3, "3", "Test3");

    dt.Rows.Add(4, "4", "Test4");

    dt.Rows.Add(4, "4", "Test3");

     

    DataView view = dt.DefaultView;

    view.Sort = "C2 ASC, C3 ASC";

    bindingSource.DataSource = view;

     

    DataGridViewTextBoxColumn col0 = new DataGridViewTextBoxColumn();

    col0.DataPropertyName = "C1";

    dataGridView1.Columns.Add(col0);

    col0.SortMode = DataGridViewColumnSortMode.Programmatic;

    col0.HeaderCell.SortGlyphDirection = SortOrder.None;

     

    DataGridViewTextBoxColumn col1 = new DataGridViewTextBoxColumn();

    col1.DataPropertyName = "C2";

    dataGridView1.Columns.Add(col1);

    col1.SortMode = DataGridViewColumnSortMode.Programmatic;

    col1.HeaderCell.SortGlyphDirection = SortOrder.Ascending;

     

    DataGridViewTextBoxColumn col2 = new DataGridViewTextBoxColumn();

    col2.DataPropertyName = "C3";

    dataGridView1.Columns.Add(col2);

    col2.SortMode = DataGridViewColumnSortMode.Programmatic;

    col2.HeaderCell.SortGlyphDirection = SortOrder.Ascending;

     


     

    (see next post for the remainder)
    5 decembrie 2007 08:10
  •       21.2 Unbound DataGridView

         To provide support for sorting on multiple columns you can handle the SortCompare event or call the Sort(IComparer) overload of the Sort method for greater sorting flexibility.

               21.2.1 Custom Sorting Using the SortCompare Event
     

             The following code example demonstrates custom sorting using a SortCompare event handler. The selected DataGridViewColumn is sorted and, if there are duplicate values in the column, the ID column is used to determine the final order.

    Code Block

    using System;

    using System.Collections.Generic;

    using System.ComponentModel;

    using System.Data;

    using System.Drawing;

    using System.Windows.Forms;

     

    class Form1 : Form

    {

        private DataGridView dataGridView1 = new DataGridView();

     

        // Establish the main entry point for the application.

        [STAThreadAttribute()]

        static void Main()

        {

            Application.EnableVisualStyles();

            Application.Run(new Form1());

        }

     

        public Form1()

        {

            // Initialize the form.

            // This code can be replaced with designer generated code.

            dataGridView1.AllowUserToAddRows = false;

            dataGridView1.Dock = DockStyle.Fill;

            dataGridView1.SortCompare += new DataGridViewSortCompareEventHandler(

                this.dataGridView1_SortCompare);

            Controls.Add(this.dataGridView1);

            this.Text = "DataGridView.SortCompare demo";

     

            PopulateDataGridView();

        }

     

        // Replace this with your own population code.

        public void PopulateDataGridView()

        {

            // Add columns to the DataGridView.

            dataGridView1.ColumnCount = 3;

     

            // Set the properties of the DataGridView columns.

            dataGridView1.Columns[0].Name = "ID";

            dataGridView1.Columns[1].Name = "Name";

            dataGridView1.Columns[2].Name = "City";

            dataGridView1.Columns["ID"].HeaderText = "ID";

            dataGridView1.Columns["Name"].HeaderText = "Name";

            dataGridView1.Columns["City"].HeaderText = "City";

     

            // Add rows of data to the DataGridView.

            dataGridView1.Rows.Add(new string[] { "1", "Parker", "Seattle" });

            dataGridView1.Rows.Add(new string[] { "2", "Parker", "New York" });

            dataGridView1.Rows.Add(new string[] { "3", "Watson", "Seattle" });

            dataGridView1.Rows.Add(new string[] { "4", "Jameson", "New Jersey" });

            dataGridView1.Rows.Add(new string[] { "5", "Brock", "New York" });

            dataGridView1.Rows.Add(new string[] { "6", "Conner", "Portland" });

     

            // Autosize the columns.

            dataGridView1.AutoResizeColumns();

        }

     

        private void dataGridView1_SortCompare(object sender,

            DataGridViewSortCompareEventArgs e)

        {

            // Try to sort based on the cells in the current column.

            e.SortResult = System.String.Compare(

                e.CellValue1.ToString(), e.CellValue2.ToString());

     

            // If the cells are equal, sort based on the ID column.

            if (e.SortResult == 0 && e.Column.Name != "ID")

            {

                e.SortResult = System.String.Compare(

                    dataGridView1.Rows[e.RowIndex1].Cells["ID"].Value.ToString(),

                    dataGridView1.Rows[e.RowIndex2].Cells["ID"].Value.ToString());

            }

            e.Handled = true;

        }

    }

     

     


    (see next post for the remainder)

    5 decembrie 2007 08:14
  •         21.2.2 Custom Sorting Using the IComparer Interface

          The following code example demonstrates custom sorting using the Sort(IComparer) overload of the Sort method, which takes an implementation of the IComparer interface to perform a multiple-column sort.

    Code Block

    using System;

    using System.Drawing;

    using System.Windows.Forms;

     

    class Form1 : Form

    {

        private DataGridView DataGridView1 = new DataGridView();

        private FlowLayoutPanel FlowLayoutPanel1 = new FlowLayoutPanel();

        private Button Button1 = new Button();

        private RadioButton RadioButton1 = new RadioButton();

        private RadioButton RadioButton2 = new RadioButton();

     

        // Establish the main entry point for the application.

        [STAThreadAttribute()]

        public static void Main()

        {

            Application.Run(new Form1());

        }

     

        public Form1()

        {

            // Initialize the form.

            // This code can be replaced with designer generated code.

            AutoSize = true;

            Text = "DataGridView IComparer sort demo";

     

            FlowLayoutPanel1.FlowDirection = FlowDirection.TopDown;

            FlowLayoutPanel1.Location = new System.Drawing.Point(304, 0);

            FlowLayoutPanel1.AutoSize = true;

     

            FlowLayoutPanel1.Controls.Add(RadioButton1);

            FlowLayoutPanel1.Controls.Add(RadioButton2);

            FlowLayoutPanel1.Controls.Add(Button1);

     

            Button1.Text = "Sort";

            RadioButton1.Text = "Ascending";

            RadioButton2.Text = "Descending";

            RadioButton1.Checked = true;

     

            Controls.Add(FlowLayoutPanel1);

            Controls.Add(DataGridView1);

        }

     

        protected override void OnLoad(EventArgs e)

        {

            PopulateDataGridView();

            Button1.Click += new EventHandler(Button1_Click);

     

            base.OnLoad(e);

        }

     

        // Replace this with your own code to populate the DataGridView.

        private void PopulateDataGridView()

        {

     

            DataGridView1.Size = new Size(300, 300);

     

            // Add columns to the DataGridView.

            DataGridView1.ColumnCount = 2;

     

            // Set the properties of the DataGridView columns.

            DataGridView1.Columns[0].Name = "First";

            DataGridView1.Columns[1].Name = "Last";

            DataGridView1.Columns["First"].HeaderText = "First Name";

            DataGridView1.Columns["Last"].HeaderText = "Last Name";

            DataGridView1.Columns["First"].SortMode =

                DataGridViewColumnSortMode.Programmatic;

            DataGridView1.Columns["Last"].SortMode =

                DataGridViewColumnSortMode.Programmatic;

     

            // Add rows of data to the DataGridView.

            DataGridView1.Rows.Add(new string[] { "Peter", "Parker" });

            DataGridView1.Rows.Add(new string[] { "James", "Jameson" });

            DataGridView1.Rows.Add(new string[] { "May", "Parker" });

            DataGridView1.Rows.Add(new string[] { "Mary", "Watson" });

            DataGridView1.Rows.Add(new string[] { "Eddie", "Brock" });

        }

     

        private void Button1_Click(object sender, EventArgs e)

        {

            if (RadioButton1.Checked == true)

            {

                DataGridView1.Sort(new RowComparer(SortOrder.Ascending));

            }

            else if (RadioButton2.Checked == true)

            {

                DataGridView1.Sort(new RowComparer(SortOrder.Descending));

            }

        }

     

        private class RowComparer : System.Collections.IComparer

        {

            private static int sortOrderModifier = 1;

     

            public RowComparer(SortOrder sortOrder)

            {

                if (sortOrder == SortOrder.Descending)

                {

                    sortOrderModifier = -1;

                }

                else if (sortOrder == SortOrder.Ascending)

                {

                    sortOrderModifier = 1;

                }

            }

     

            public int Compare(object x, object y)

            {

                DataGridViewRow DataGridViewRow1 = (DataGridViewRow)x;

                DataGridViewRow DataGridViewRow2 = (DataGridViewRow)y;

     

                // Try to sort based on the Last Name column.

                int CompareResult = System.String.Compare(

                    DataGridViewRow1.Cells[1].Value.ToString(),

                    DataGridViewRow2.Cells[1].Value.ToString());

     

                // If the Last Names are equal, sort based on the First Name.

                if (CompareResult == 0)

                {

                    CompareResult = System.String.Compare(

                        DataGridViewRow1.Cells[0].Value.ToString(),

                        DataGridViewRow2.Cells[0].Value.ToString());

                }

                return CompareResult * sortOrderModifier;

            }

        }

    }

     

     



    5 decembrie 2007 08:16
  • 22.   How do I perform drag and drop reorder of rows?

    Drag and dropping to reorder rows is not built into the DataGridView, but following standard drag and drop code you can easily add this functionality to the DataGridView. The code fragment below shows how you can accomplish this. It assumes that you have a DataGridView control on your form named dataGridView1 and that the grid's AllowDrop property is true and the necessary events are hooked up to the correct event handlers.

     

    Code Block

    private Rectangle dragBoxFromMouseDown;

            private int rowIndexFromMouseDown;

            private int rowIndexOfItemUnderMouseToDrop;

            private void dataGridView1_MouseMove(object sender, MouseEventArgs e)

            {

                if ((e.Button & MouseButtons.Left) == MouseButtons.Left)

                {

                    // If the mouse moves outside the rectangle, start the drag.

                    if (dragBoxFromMouseDown != Rectangle.Empty &&

                        !dragBoxFromMouseDown.Contains(e.X, e.Y))

                    {

     

                        // Proceed with the drag and drop, passing in the list item.                   

                        DragDropEffects dropEffect = dataGridView1.DoDragDrop(

                        dataGridView1.Rows[rowIndexFromMouseDown],

                        DragDropEffects.Move);

                    }

                }

            }

     

            private void dataGridView1_MouseDown(object sender, MouseEventArgs e)

            {

                // Get the index of the item the mouse is below.

                rowIndexFromMouseDown = dataGridView1.HitTest(e.X, e.Y).RowIndex;

     

                if (rowIndexFromMouseDown != -1)

                {

                    // Remember the point where the mouse down occurred.

                    // The DragSize indicates the size that the mouse can move

                    // before a drag event should be started.               

                    Size dragSize = SystemInformation.DragSize;

     

                    // Create a rectangle using the DragSize, with the mouse position being

                    // at the center of the rectangle.

                    dragBoxFromMouseDown = new Rectangle(new Point(e.X - (dragSize.Width / 2),

                                                                   e.Y - (dragSize.Height / 2)),

                                        dragSize);

                }

                else

                    // Reset the rectangle if the mouse is not over an item in the ListBox.

                    dragBoxFromMouseDown = Rectangle.Empty;

            }

     

            private void dataGridView1_DragOver(object sender, DragEventArgs e)

            {

                e.Effect = DragDropEffects.Move;

            }

     

            private void dataGridView1_DragDrop(object sender, DragEventArgs e)

            {

                // The mouse locations are relative to the screen, so they must be

                // converted to client coordinates.

                Point clientPoint = dataGridView1.PointToClient(new Point(e.X, e.Y));

     

                // Get the row index of the item the mouse is below.

                rowIndexOfItemUnderMouseToDrop =

                    dataGridView1.HitTest(clientPoint.X, clientPoint.Y).RowIndex;

     

                // If the drag operation was a move then remove and insert the row.

                if (e.Effect == DragDropEffects.Move)

                {

                    DataGridViewRow rowToMove = e.Data.GetData(

                        typeof(DataGridViewRow)) as DataGridViewRow;

                    dataGridView1.Rows.RemoveAt(rowIndexFromMouseDown);

                    dataGridView1.Rows.Insert(rowIndexOfItemUnderMouseToDrop, rowToMove);

     

                }

            }

     

     


    5 decembrie 2007 08:17
  • 23. How do I make the last column wide enough to occupy all the remaining client area of the grid?


    By setting the AutoSizeMode for the last column to Fill the column will size itself to fill in the remaining client area of the grid. Optionally you can set the last column's MinimumWidth if you want to keep the column from sizing too small.

    5 decembrie 2007 08:19
  • 24.    How do I have the cell text wrap?

    By default, text in a DataGridViewTextBoxCell does not wrap. This can be controlled via the WrapMode property on the cell style (e.g. DataGridView.DefaultCellStyle.WrapMode). Set the WrapMode property of a DataGridViewCellStyle to one of the DataGridViewTriState enumeration values.
    The following code example uses the DataGridView.DefaultCellStyle property to set the wrap mode for the entire control.

          

    Code Block

    this.dataGridView1.DefaultCellStyle.WrapMode = DataGridViewTriState.True;


     

     

    5 decembrie 2007 08:20
  • 25.   How do I make the image column not show any images?


    By default the image column and cell convert null values to the standard "X" image . You can make no image show up by changing the column’s NullValue property to null. The following code example sets the NullValue for an image column:

           this.dataGridViewImageColumn1.DefaultCellStyle.NullValue = null;

    5 decembrie 2007 08:22
  • 26. How do I enable typing in the combo box cell?

          By default a DataGridViewComboBoxCell does not support typing into the cell. There are reasons though that typing into the combo box works well for your application. To enable this, two things have to be done. First the DropDownStyle property of the ComboBox editing control needs to be set to DropDown to enable typing in the combo box. The second thing that needs to be done is to ensure that the value that the user typed into the cell is added to the combo box items collection. This is due to the requirement  that a combo box cells value must be in the items collection or else a DataError event is raised. The appropriate place to add the value to the items collection is in the CellValidating event handler.

    Code Block


            private
    void dataGridView1_CellValidating(object sender,

                     DataGridViewCellValidatingEventArgs e)

            {

                if (e.ColumnIndex == comboBoxColumn.DisplayIndex)

                {

                    if (!this.comboBoxColumn.Items.Contains(e.FormattedValue))

                    {

                        this.comboBoxColumn.Items.Add(e.FormattedValue);

                    }

                }

            }

     

            private void dataGridView1_EditingControlShowing(object sender,

                    DataGridViewEditingControlShowingEventArgs e)

            {

                if (this.dataGridView1.CurrentCellAddress.X == comboBoxColumn.DisplayIndex)

                {

                    ComboBox cb = e.Control as ComboBox;

                    if (cb != null)

                    {

                        cb.DropDownStyle = ComboBoxStyle.DropDown;

                    }

                }

            }

     

     

    5 decembrie 2007 08:27
  • 27. How do I have a combo box column display a sub set of data based upon the value of a different combo box column?

         Sometimes data that you want to display in the DataGridView has a relationship between two tables such as a category and subcategory. You want to let the user select the category and then choose between a subcategory based upon the category. This is possible with the DataGridView by using two combo box columns. To enable this, two versions of the filtered list (subcategory) needs to be created. One list has no filter applied while the other one will be filtered only when the user is editing a subcategory cell. Two lists are required due to the requirement  that a combo box cells value must be in the items collection or else a DataError event is raised. In this case, since all combo box cells in the column use the same datasource if you filter the datasource for one row then a combo box cell in another row might not have its value visible in the datasource, thus causing a DataError event.

         The below example uses the Northwind database to display related data from the Territory and Region tables (a territory is in a specific region.) Using the category and subcategory concept, the Region is the category and the Territory is the subcategory.


    Code Block


            private
    void Form1_Load(object sender, EventArgs e)

            {

                this.territoriesTableAdapter.Fill(this.northwindDataSet.Territories);

                this.regionTableAdapter.Fill(this.northwindDataSet.Region);

     

                // Setup BindingSource for filtered view.

                filteredTerritoriesBS = new BindingSource();

                DataView dv = new DataView(northwindDataSet.Tables["Territories"]);

                filteredTerritoriesBS.DataSource = dv;

     

            }

     

            private void dataGridView1_CellBeginEdit(object sender,

                     DataGridViewCellCancelEventArgs e)

            {

                if (e.ColumnIndex == territoryComboBoxColumn.Index)

                {

                    // Set the combobox cell datasource to the filtered BindingSource

                    DataGridViewComboBoxCell dgcb = (DataGridViewComboBoxCell)dataGridView1

                                    [e.ColumnIndex, e.RowIndex];

                    dgcb.DataSource = filteredTerritoriesBS;

     

                    // Filter the BindingSource based upon the region selected

                    this.filteredTerritoriesBS.Filter = "RegionID = " +

                        this.dataGridView1[e.ColumnIndex - 1, e.RowIndex].Value.ToString();

                }

            }

     

            private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)

            {

                if (e.ColumnIndex == this.territoryComboBoxColumn.Index)

                {

                    // Reset combobox cell to the unfiltered BindingSource

                    DataGridViewComboBoxCell dgcb = (DataGridViewComboBoxCell)dataGridView1

                                    [e.ColumnIndex, e.RowIndex];

                    dgcb.DataSource = territoriesBindingSource; //unfiltered

     

                    this.filteredTerritoriesBS.RemoveFilter();

                }

            }

     

     

    5 decembrie 2007 08:30
  • 28. How do I show the error icon when the user is editing the cell?

    Sometimes when using the error text and icon feature you want an immediate feedback to the user that something that they typed into a cell is incorrect. By default when setting the ErrorText property the error icon will not appear if the cell is in edit mode such as a text box or combo box cell.

    The below sample demonstrates how you can set a cell's padding in the CellValidating event to provide spacing for the error icon. Since padding by default affects the location of the error icon the sample uses the CellPainting to move the position of the icon for painting. Lastly, the sample uses the tooltip control to display a custom tooltip when the mouse is over the cell to indicate what the problem is. This sample could also be written as a custom cell that overrides GetErrorIconBounds method to provide a location for the error icon that was independent of the padding.  

    Code Block


     

    private ToolTip errorTooltip;

    private Point cellInError = new Point(-2, -2);

    public Form1()

    {

        InitializeComponent();

        dataGridView1.ColumnCount = 3;

        dataGridView1.RowCount = 10;

    }

     

    private void dataGridView1_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)

    {

        if (dataGridView1.IsCurrentCellDirty)

        {

            if (e.FormattedValue.ToString() == "BAD")

            {

                DataGridViewCell cell = dataGridView1[e.ColumnIndex, e.RowIndex];

                cell.ErrorText = "Invalid data entered in cell";

     

                // increase padding for icon. This moves the editing control

                if (cell.Tag == null)

                {

                    cell.Tag = cell.Style.Padding;

                    cell.Style.Padding = new Padding(0, 0, 18, 0);

                    cellInError = new Point(e.ColumnIndex, e.RowIndex);

                }

                if (errorTooltip == null)

                {

                    errorTooltip = new ToolTip();

                    errorTooltip.InitialDelay = 0;

                    errorTooltip.ReshowDelay = 0;

                    errorTooltip.Active = false;

                }

     

                e.Cancel = true;

            }

        }

    }

     

    private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)

    {

        if (dataGridView1.IsCurrentCellDirty && !String.IsNullOrEmpty(e.ErrorText))

        {

            // paint everything except error icon

            e.Paint(e.ClipBounds, DataGridViewPaintParts.All &

                            ~(DataGridViewPaintParts.ErrorIcon));

     

            // now move error icon over to fill in the padding space

            GraphicsContainer container = e.Graphics.BeginContainer();

            e.Graphics.TranslateTransform(18, 0);

            e.Paint(this.ClientRectangle, DataGridViewPaintParts.ErrorIcon);

            e.Graphics.EndContainer(container);

     

            e.Handled = true;

        }

    }

     

    private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)

    {

        if (dataGridView1[e.ColumnIndex, e.RowIndex].ErrorText != String.Empty)

        {

            DataGridViewCell cell = dataGridView1[e.ColumnIndex, e.RowIndex];

            cell.ErrorText = String.Empty;

            cellInError = new Point(-2,-2);

     

            // restore padding for cell. This moves the editing control

            cell.Style.Padding = (Padding)cell.Tag;

     

            // hide and dispose tooltip

            if (errorTooltip != null)

            {

                errorTooltip.Hide(dataGridView1);

                errorTooltip.Dispose();

                errorTooltip = null;

            }

        }

    }

     

    // show and hide the tooltip for error

    private void dataGridView1_CellMouseMove(object sender,

                            DataGridViewCellMouseEventArgs e)

    {

        if (cellInError.X == e.ColumnIndex &&

            cellInError.Y == e.RowIndex)

        {

            DataGridViewCell cell = dataGridView1[e.ColumnIndex, e.RowIndex];

     

            if (cell.ErrorText != String.Empty)

            {

                if (!errorTooltip.Active)

                {

                    errorTooltip.Show(cell.ErrorText, dataGridView1, 1000);

                }

                errorTooltip.Active = true;

            }

        }

    }

     

    private void dataGridView1_CellMouseLeave(object sender, DataGridViewCellEventArgs e)

    {

        if (cellInError.X == e.ColumnIndex &&

            cellInError.Y == e.RowIndex)

        {

            if (errorTooltip.Active)

            {

                errorTooltip.Hide(dataGridView1);

                errorTooltip.Active = false;

            }

        }

    }

     

    5 decembrie 2007 08:33
  • 29. How do I show unbound data along with bound data?

    The data you display in the DataGridView control will normally come from a data source of some kind, but you might want to display a column of data that does not come from the data source. This kind of column is called an unbound column. Unbound columns can take many forms. As discussed in the data section above, you can use virtual mode to display additional data along with bound data.

    The following code example demonstrates how to create an unbound column of check box cells to enable the user to select database records to process. The grid is put into virtual mode and responds to the necessary events. The selected records are kept by ID in a dictionary to allow the user to sort the content but not lose the checked rows.

    Code Block


    private
    System.Collections.Generic.Dictionary<int, bool> checkState;

    private void Form1_Load(object sender, EventArgs e)

    {

        dataGridView1.AutoGenerateColumns = false;

        dataGridView1.DataSource = customerOrdersBindingSource;

     

        // The check box column will be virtual.

        dataGridView1.VirtualMode = true;

        dataGridView1.Columns.Insert(0, new DataGridViewCheckBoxColumn());

     

        // Initialize the dictionary that contains the boolean check state.

        checkState = new Dictionary<int, bool>();

    }

    private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)

    {

        // Update the status bar when the cell value changes.

        if (e.ColumnIndex == 0 && e.RowIndex != -1)

        {

            // Get the orderID from the OrderID column.

            int orderID = (int)dataGridView1.Rows[e.RowIndex].Cells["OrderID"].Value;

            checkState[orderID] = (bool)dataGridView1.Rows[e.RowIndex].Cells[0].Value;

     

    }

     

    private void dataGridView1_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)

    {

        // Handle the notification that the value for a cell in the virtual column

        // is needed. Get the value from the dictionary if the key exists.

     

        if (e.ColumnIndex == 0)

        {

            int orderID = (int)dataGridView1.Rows[e.RowIndex].Cells["OrderID"].Value;

            if (checkState.ContainsKey(orderID))

            {

                e.Value = checkState[orderID];

            }

            else

                e.Value = false;

        }

     

    }

     

    private void dataGridView1_CellValuePushed(object sender, DataGridViewCellValueEventArgs e)

    {

        // Handle the notification that the value for a cell in the virtual column

        // needs to be pushed back to the dictionary.

     

        if (e.ColumnIndex == 0)

        {

            // Get the orderID from the OrderID column.

            int orderID = (int)dataGridView1.Rows[e.RowIndex].Cells["OrderID"].Value;

     

            // Add or update the checked value to the dictionary depending on if the

            // key (orderID) already exists.

            if (!checkState.ContainsKey(orderID))

            {

                checkState.Add(orderID, (bool)e.Value);

            }

            else

                checkState[orderID] = (bool)e.Value;

        }

    }

     

     

     

    5 decembrie 2007 08:35
  • 30. How do I show data that comes from two tables?

    The DataGridView does not provide any new features apart from virtual mode to enable this. What you can do is use the JoinView class described in the following article http://support.microsoft.com/default.aspx?scid=kb;en-us;325682. Using this class you can join two or more DataTables together. This JoinView can then be databound to the DataGridView.

    5 decembrie 2007 08:36
  • 31. How do I show master-details?

    One of the most common scenarios for using the DataGridView control is the master/detail form, in which a parent/child relationship between two database tables is displayed. Selecting rows in the master table causes the detail table to update with the corresponding child data.

    Implementing a master/detail form is easy using the interaction between the DataGridView control and the BindingSource component. The below sample will show two related tables in the Northwind SQL Server sample database: Customers and Orders. By selecting a customer in the master DataGridView all the orders for the customer will appear in the detail DataGridView.

    Code Block

    using System;

    using System.Data;

    using System.Data.SqlClient;

    using System.Windows.Forms;

     

    public class Form1 : System.Windows.Forms.Form

    {

        private DataGridView masterDataGridView = new DataGridView();

        private BindingSource masterBindingSource = new BindingSource();

        private DataGridView detailsDataGridView = new DataGridView();

        private BindingSource detailsBindingSource = new BindingSource();

     

        [STAThreadAttribute()]

        public static void Main()

        {

            Application.Run(new Form1());

        }

     

        // Initializes the form.

        public Form1()

        {

            masterDataGridView.Dock = DockStyle.Fill;

            detailsDataGridView.Dock = DockStyle.Fill;

     

            SplitContainer splitContainer1 = new SplitContainer();

            splitContainer1.Dock = DockStyle.Fill;

            splitContainer1.Orientation = Orientation.Horizontal;

            splitContainer1.Panel1.Controls.Add(masterDataGridView);

            splitContainer1.Panel2.Controls.Add(detailsDataGridView);

     

            this.Controls.Add(splitContainer1);

            this.Load += new System.EventHandler(Form1_Load);

            this.Text = "DataGridView master/detail demo";

        }

     

        private void Form1_Load(object sender, System.EventArgs e)

        {

            // Bind the DataGridView controls to the BindingSource

            // components and load the data from the database.

            masterDataGridView.DataSource = masterBindingSource;

            detailsDataGridView.DataSource = detailsBindingSource;

            GetData();

     

            // Resize the master DataGridView columns to fit the newly loaded data.

            masterDataGridView.AutoResizeColumns();

     

            // Configure the details DataGridView so that its columns automatically

            // adjust their widths when the data changes.

            detailsDataGridView.AutoSizeColumnsMode =

                DataGridViewAutoSizeColumnsMode.AllCells;

        }

     

        private void GetData()

        {

            try

            {

                // Specify a connection string. Replace the given value with a

                // valid connection string for a Northwind SQL Server sample

                // database accessible to your system.

                String connectionString =

                    "Integrated Security=SSPI;Persist Security Info=False;" +

                    "Initial Catalog=Northwind;Data Source=localhost";

                SqlConnection connection = new SqlConnection(connectionString);

     

                // Create a DataSet.

                DataSet data = new DataSet();

                data.Locale = System.Globalization.CultureInfo.InvariantCulture;

     

                // Add data from the Customers table to the DataSet.

                SqlDataAdapter masterDataAdapter = new

                    SqlDataAdapter("select * from Customers", connection);

                masterDataAdapter.Fill(data, "Customers");

     

                // Add data from the Orders table to the DataSet.

                SqlDataAdapter detailsDataAdapter = new

                    SqlDataAdapter("select * from Orders", connection);

                detailsDataAdapter.Fill(data, "Orders");

     

                // Establish a relationship between the two tables.

                DataRelation relation = new DataRelation("CustomersOrders",

                    data.Tables["Customers"].Columns["CustomerID"],

                    data.Tables["Orders"].Columns["CustomerID"]);

                data.Relations.Add(relation);

     

                // Bind the master data connector to the Customers table.

                masterBindingSource.DataSource = data;

                masterBindingSource.DataMember = "Customers";

     

                // Bind the details data connector to the master data connector,

                // using the DataRelation name to filter the information in the

                // details table based on the current row in the master table.

                detailsBindingSource.DataSource = masterBindingSource;

                detailsBindingSource.DataMember = "CustomersOrders";

            }

            catch (SqlException)

            {

                MessageBox.Show("To run this example, replace the value of the " +

                    "connectionString variable with a connection string that is " +

                    "valid for your system.");

            }

        }

    }

     

     

    5 decembrie 2007 08:38
  • 34. How do I commit the data to the database when clicking on a toolstrip button?

    By default, toolbars and menus do not force validation for controls. Validation is a required part of validating and updating the data in a bound control. Once the form and all bound controls are validated, any current edits need to be committed. Finally, the table adapter needs to push its changes back to the database. To do this, put the following three lines in a click event handler on your form:

    Code Block

           
            this
    .Validate();

            this.customersBindingSource.EndEdit();        

            this.customersTableAdapter.Update(this.northwindDataSet.Customers);

     

     

     

     

    5 decembrie 2007 08:43
  • 35. How do I display a confirmation dialog when the user tries to delete a row?

          When the user selects a row in the DataGridView and hits the delete key, the UserDeletingRow event fires. You can prompt the user if they want to continue deleting the row. It is recommended that you only do this if the row being deleted is not the new row. Add the following code to the UserDeletingRow event handler to perform this:

    Code Block


    if
    (!e.Row.IsNewRow)

    {

        DialogResult response = MessageBox.Show("Are you sure?", "Delete row?",

                             MessageBoxButtons.YesNo,

                             MessageBoxIcon.Question,

                             MessageBoxDefaultButton.Button2);

         if (response == DialogResult.No)

           e.Cancel = true;

    }

     

     

     

     

    5 decembrie 2007 08:45