Windows Develop Bookmark and Share   
 index > Windows Forms Data Controls and Databinding > DataGridView cell editing
 

DataGridView cell editing

Hello,

In Microsoft Excel last versions, when editing a cell, if you are entering a value which size is larger than the cell size, the cell pass over the others and becomes dynamically as large as the value in order to see all the value (for example if it's a huge string it allows to see it entirely).
Does the DataGridView provides a feature like this ?

Thank you :)

Alex Bell
Alex Bell  Wednesday, July 20, 2005 9:22 AM

The DataGridView doesn't do editing like Excel where the textbox grows larger when you add more text. You might be able to perform some advanced customziation. Check out the PositionEditingControl and PositionEditingPanel methods on DataGridViewCell. You will also need to return true from the RepositionEditingControlOnValueChange property on IDataGridViewEditingControl interface.

-mark
DataGridView Program Manager
Microsoft
This post is provided "as-is"

Mark Rideout  Wednesday, July 20, 2005 10:50 PM

The DataGridViewCell::PositionEditingControl and DataGridViewCell::PositionEditingPanel are virtual/overridable method. You need to sub-class the DataGridViewCell in order to get access (override) this method.  See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbcn7/html/vaconInheritanceForBasicLanguage.asp for details on sub-classing using Visual Basic.

Note in your case you will want to sub-class the DataGridViewTextBoxCell.
 
Here is some code that will help:

Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Dim c As DataGridViewTextBoxColumn = New DataGridViewTextBoxColumn()
        c.CellTemplate = New EditableMergedCell()
        dataGridView1.Columns.Add(c)

        c = New DataGridViewTextBoxColumn()
        dataGridView1.Columns.Add(c)

        dataGridView1.RowCount = 10

    End Sub

End Class
Public Class EditableMergedCell
    Inherits DataGridViewTextBoxCell

    Public Overrides Sub PositionEditingControl(ByVal setLocation As Boolean, ByVal setSize As Boolean, ByVal cellBounds As System.Drawing.Rectangle, ByVal cellClip As System.Drawing.Rectangle, ByVal cellStyle As System.Windows.Forms.DataGridViewCellStyle, ByVal singleVerticalBorderAdded As Boolean, ByVal singleHorizontalBorderAdded As Boolean, ByVal isFirstDisplayedColumn As Boolean, ByVal isFirstDisplayedRow As Boolean)
        MyBase.PositionEditingControl(setLocation, setSize, cellBounds, cellClip, cellStyle, singleVerticalBorderAdded, singleHorizontalBorderAdded, isFirstDisplayedColumn, isFirstDisplayedRow)
    End Sub
    Public Overrides Function PositionEditingPanel(ByVal cellBounds As System.Drawing.Rectangle, ByVal cellClip As System.Drawing.Rectangle, ByVal cellStyle As System.Windows.Forms.DataGridViewCellStyle, ByVal singleVerticalBorderAdded As Boolean, ByVal singleHorizontalBorderAdded As Boolean, ByVal isFirstDisplayedColumn As Boolean, ByVal isFirstDisplayedRow As Boolean) As System.Drawing.Rectangle

        ' the cell rectangle is the bounds of the merged cell
        Dim mergedRectangle As Rectangle = New Rectangle(cellBounds.Location, New Size(cellBounds.Width * 2, cellBounds.Height))

        ' the cell clip tells the grid how much of the merged cell is visible.
        Dim mergedCellClip As Rectangle = New Rectangle(cellClip.Location, New Size(cellClip.Width * 2, cellClip.Height))
        ' -------------------
        ' NOTE: This is how the grid determins the cell clip by default:
        'Dim cellClip as Rectangle = cellBounds
        '// Need to clip the zones of the frozen columns and rows and headers.
        'If (not me.Columns(this.ptCurrentCell.X).Frozen) then
        '
        '    Dim totalVisibleFrozenWidth as Integer = me.Columns.GetColumnsWidth(DataGridViewElementStates.Visible or DataGridViewElementStates.Frozen)
        '    If (not me.RightToLeftInternal) Then
        '        editingZone.X += totalVisibleFrozenWidth
        '    End If
        '    editingZone.Width = Math.Max(0, editingZone.Width - totalVisibleFrozenWidth)
        'End If
        'If ((me.Rows.GetRowState(this.ptCurrentCell.Y) and DataGridViewElementStates.Frozen) = 0) Then
        '    Dim totalVisibleFrozenHeight as Integer = me.Rows.GetRowsHeight(DataGridViewElementStates.Visible or DataGridViewElementStates.Frozen)
        '    editingZone.Y += totalVisibleFrozenHeight
        'End If
        'cellClip.Intersect(editingZone)
        '---------------------------

        Return MyBase.PositionEditingPanel(cellBounds, cellClip, cellStyle, singleVerticalBorderAdded, singleHorizontalBorderAdded, isFirstDisplayedColumn, isFirstDisplayedRow)
    End Function
End Class

 



-mark
DataGridView Program Manager
Microsoft
This post is provided "as-is"

Mark Rideout  Thursday, July 21, 2005 10:17 PM
I have just discovered the DataGridViewTextBoxEditingControl control and I like to know if it allows to make what I want ?
I have a datagridview with textboxcolumns and I have tried to use this DataGridViewTextBoxEditingControl but I haven't successed :'(
If this control is the solution, could you show me simply how it works please ?
I haven't seen any sample :'( on how to use it...

Thank you very much for helping me.
Alex Bell  Wednesday, July 20, 2005 3:50 PM

The DataGridView doesn't do editing like Excel where the textbox grows larger when you add more text. You might be able to perform some advanced customziation. Check out the PositionEditingControl and PositionEditingPanel methods on DataGridViewCell. You will also need to return true from the RepositionEditingControlOnValueChange property on IDataGridViewEditingControl interface.

-mark
DataGridView Program Manager
Microsoft
This post is provided "as-is"

Mark Rideout  Wednesday, July 20, 2005 10:50 PM
Thank you very much for helping me :D

I've tried to use these functions but I haven't succeded...
Before to try to give a dynamic size to my EditingControl, I have tried to give it a fixed larger size than the CurrentCell size, but when I edit my cell, it keeps always the same behaviour...

I haven't successfully used the DataGridView.CurrentCell.PositionEditingControl method or the DataGridView.CurrentCell.PositionEditingPanel function.
The DataGridView.EditingControl property is just a get.

I'm just a student, I haven't a great experience and I haven't reflexes for do that easily...
Could you give me more explanations or examples of how to do that please ?

Thank you very much again ^^
Alex Bell  Thursday, July 21, 2005 9:48 PM

The DataGridViewCell::PositionEditingControl and DataGridViewCell::PositionEditingPanel are virtual/overridable method. You need to sub-class the DataGridViewCell in order to get access (override) this method.  See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbcn7/html/vaconInheritanceForBasicLanguage.asp for details on sub-classing using Visual Basic.

Note in your case you will want to sub-class the DataGridViewTextBoxCell.
 
Here is some code that will help:

Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Dim c As DataGridViewTextBoxColumn = New DataGridViewTextBoxColumn()
        c.CellTemplate = New EditableMergedCell()
        dataGridView1.Columns.Add(c)

        c = New DataGridViewTextBoxColumn()
        dataGridView1.Columns.Add(c)

        dataGridView1.RowCount = 10

    End Sub

End Class
Public Class EditableMergedCell
    Inherits DataGridViewTextBoxCell

    Public Overrides Sub PositionEditingControl(ByVal setLocation As Boolean, ByVal setSize As Boolean, ByVal cellBounds As System.Drawing.Rectangle, ByVal cellClip As System.Drawing.Rectangle, ByVal cellStyle As System.Windows.Forms.DataGridViewCellStyle, ByVal singleVerticalBorderAdded As Boolean, ByVal singleHorizontalBorderAdded As Boolean, ByVal isFirstDisplayedColumn As Boolean, ByVal isFirstDisplayedRow As Boolean)
        MyBase.PositionEditingControl(setLocation, setSize, cellBounds, cellClip, cellStyle, singleVerticalBorderAdded, singleHorizontalBorderAdded, isFirstDisplayedColumn, isFirstDisplayedRow)
    End Sub
    Public Overrides Function PositionEditingPanel(ByVal cellBounds As System.Drawing.Rectangle, ByVal cellClip As System.Drawing.Rectangle, ByVal cellStyle As System.Windows.Forms.DataGridViewCellStyle, ByVal singleVerticalBorderAdded As Boolean, ByVal singleHorizontalBorderAdded As Boolean, ByVal isFirstDisplayedColumn As Boolean, ByVal isFirstDisplayedRow As Boolean) As System.Drawing.Rectangle

        ' the cell rectangle is the bounds of the merged cell
        Dim mergedRectangle As Rectangle = New Rectangle(cellBounds.Location, New Size(cellBounds.Width * 2, cellBounds.Height))

        ' the cell clip tells the grid how much of the merged cell is visible.
        Dim mergedCellClip As Rectangle = New Rectangle(cellClip.Location, New Size(cellClip.Width * 2, cellClip.Height))
        ' -------------------
        ' NOTE: This is how the grid determins the cell clip by default:
        'Dim cellClip as Rectangle = cellBounds
        '// Need to clip the zones of the frozen columns and rows and headers.
        'If (not me.Columns(this.ptCurrentCell.X).Frozen) then
        '
        '    Dim totalVisibleFrozenWidth as Integer = me.Columns.GetColumnsWidth(DataGridViewElementStates.Visible or DataGridViewElementStates.Frozen)
        '    If (not me.RightToLeftInternal) Then
        '        editingZone.X += totalVisibleFrozenWidth
        '    End If
        '    editingZone.Width = Math.Max(0, editingZone.Width - totalVisibleFrozenWidth)
        'End If
        'If ((me.Rows.GetRowState(this.ptCurrentCell.Y) and DataGridViewElementStates.Frozen) = 0) Then
        '    Dim totalVisibleFrozenHeight as Integer = me.Rows.GetRowsHeight(DataGridViewElementStates.Visible or DataGridViewElementStates.Frozen)
        '    editingZone.Y += totalVisibleFrozenHeight
        'End If
        'cellClip.Intersect(editingZone)
        '---------------------------

        Return MyBase.PositionEditingPanel(cellBounds, cellClip, cellStyle, singleVerticalBorderAdded, singleHorizontalBorderAdded, isFirstDisplayedColumn, isFirstDisplayedRow)
    End Function
End Class

 



-mark
DataGridView Program Manager
Microsoft
This post is provided "as-is"

Mark Rideout  Thursday, July 21, 2005 10:17 PM

This is my implementation. There seems to be a few problems with wrapping but.

public class MemoCell: DataGridViewTextBoxCell

{

public override void InitializeEditingControl(int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)

{

dataGridViewCellStyle.WrapMode = DataGridViewTriState.True;

base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle);

}

public override void PositionEditingControl(bool setLocation, bool setSize, Rectangle cellBounds, Rectangle cellClip, DataGridViewCellStyle cellStyle, bool singleVerticalBorderAdded, bool singleHorizontalBorderAdded, bool isFirstDisplayedColumn, bool isFirstDisplayedRow)

{

base.PositionEditingControl(setLocation, setSize, cellBounds, cellClip, cellStyle, singleVerticalBorderAdded, singleHorizontalBorderAdded, isFirstDisplayedColumn, isFirstDisplayedRow);

}

public override Rectangle PositionEditingPanel(Rectangle cellBounds, Rectangle cellClip, DataGridViewCellStyle cellStyle, bool singleVerticalBorderAdded, bool singleHorizontalBorderAdded, bool isFirstDisplayedColumn, bool isFirstDisplayedRow)

{

string value = (string)this.EditedFormattedValue;

Size maxSize = MaxSize(cellBounds.Location);

Size stringSize = MeasureString(value, cellStyle.Font, new SizeF((float)maxSize.Width, (float)maxSize.Height));

Console.WriteLine(stringSize);

Rectangle maxRectangle = new Rectangle(cellBounds.Location, MaxSize(cellBounds.Location));

int finalWidth = Math.Max(stringSize.Width, cellBounds.Width);

int finalHeight = Math.Max(stringSize.Height, cellBounds.Height);

Rectangle finalRectangle = new Rectangle(cellBounds.Location, new Size(finalWidth, finalHeight));

return base.PositionEditingPanel(finalRectangle, finalRectangle, cellStyle, singleVerticalBorderAdded, singleHorizontalBorderAdded, isFirstDisplayedColumn, isFirstDisplayedRow);

}

public override Type EditType

{

get

{

return typeof(MemoTextBox);

}

}

public Size MeasureString(string value, Font font, SizeF layoutArea)

{

int characters,lines;

int lineHeight;

Graphics g = Graphics.FromHwnd(this.DataGridView.Handle);

lineHeight = g.MeasureString("MeasureString", font).ToSize().Height;

Size size = g.MeasureString(value, font, layoutArea, new StringFormat(StringFormatFlags.MeasureTrailingSpaces), out characters, out lines).ToSize();

Console.WriteLine("Characters{0}, lines{1}", characters, lines);

if (value.EndsWith(Environment.NewLine))

{

lines += 1;

}

size.Height = (lineHeight * lines);

return size;

}

private Size MaxSize(Point relativeLocation)

{

Size gridSize = this.DataGridView.Size;

int widthLeftover = gridSize.Width - relativeLocation.X;

int heightLeftover = gridSize.Height - relativeLocation.Y;

if (widthLeftover < 0

|| heightLeftover < 0)

{

throw new Exception("Tp can't be right!");

}

return new Size(widthLeftover, heightLeftover);

}

}

angrylala  Tuesday, November 07, 2006 11:20 PM

You can use google to search for other answers

Custom Search

More Threads

• Problem with the datagridview.button col button color not change in vb.net 2008
• datagirdview paging support
• sorting datagrid view on update
• Retrieve data from a selected row in DataGridView
• 2-state DataGridBoolColumn style
• How to bind a custom business object that contains other business objects?
• Add New row to DataTable doesn't refresh DataGridView control. Please Help!
• Sorting problem in DataGridView
• Datagridview CheckBoxColumn
• Problems with the windows.forms.BindingSource