3

I am trying to create a chatbot. I will be very honest, UI is not my forte. I am working on the backend of the chatbot as in the logic part, but for testing I need a proper working UI. So, I opted for easier to use winforms. I created a single column DataGridView and all the text written in a textbox at the bottom part of the chat window will appear as DataGridView rows. The winform is anchored to grow in all directions. So, when I load the exe, it shows as a miniature window, when I maximize it, the DataGridView portion and the textbox grow accordingly.

When I type a long string and the winform is not in a maximized state, the text is not wrapped in the row in the visible area. It extends horizontally and so obviously not visible in the screen. When I maximize the window, I can see the text. When I give a veryyy long string and maximize the window, only that much of the string is shown in the row as it can fit in the screen size.

What I want to do: I want the text to wrap automatically in the rows, so that, irrespective of whether my window is maximized or minimized, I can see the entire string in the window in a wrapped format.

What I have tried:

dataGridView1.DefaultCellStyle.WrapMode = DataGridViewTriState.True;
dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
KChow
  • 317
  • 3
  • 15
  • @Natrium that question refers to a textbox, this one to a datagridview, which is very different. – stuartd Sep 23 '16 at 12:39
  • It works in my test program. Can it be that you override the DefaultCellStyle.WapMode somewhere? check this for instance in your form load, using linq; dataGridView1.Rows.SelectMany(row => row.Cells).All(cell => cell.InheritedStyle == DataGridViewTriState.True); – Harald Coppoolse Sep 23 '16 at 13:04
  • The thing is, when the words are separated with spaces, it wraps, but if its a single long string then wrapping doesn't work. – KChow Sep 23 '16 at 14:07
  • `DataGridViewTextBox` performs wrapping using word-break. It means if you have a long text, the break will just apply at the end of words. Based on your requirement, you need character-break when word wrapping. To do so, you need to create a custom cell and perform character-break wrapping. – Reza Aghaei Sep 25 '16 at 02:30

1 Answers1

3

DataGridViewTextBox performs wrapping using word-break. It means if you have a long text, the break will just apply at the end of words. Based on your requirement, you need character-break when word wrapping. To do so, you need to create a custom cell and perform character-break wrapping this way:

  • Override GetPreferredSize method to calculate the height of Cell/Row based on character break word wrapping. To so so you can use Graphics.MeasureString method.

  • Override Paint method to draw the wrapped string with character break using Graphics.DrawString method.

You can perform these settings:

  • To use the width of DataGridView for your column, you should set it's AutoSizeMode to Fill. This way, your column width will fill the grid and will be change its size according to grid size. Also if you had more than one column, you can set FillWeight to control the percent of column size relative to other columns.

  • To wrap the text in column you should set DefaultCellStyle.WrapMode of the column to DataGridViewTriState.True.

  • To make the rows auto-size you should set AutoSizeRowMode of DataGridView to DataGridViewAutoSizeRowsMode.AllCells.

  • Register the custom cell which we created as CellTemplate of the column.

MyDataGridViewTextBoxCell

This cell performs text-wrapping using character-break instead of word break.

public class MyDataGridViewTextBoxCell:DataGridViewTextBoxCell
{
    protected override Size GetPreferredSize(Graphics graphics, 
        DataGridViewCellStyle cellStyle, int rowIndex, Size constraintSize)
    {
        if(cellStyle.WrapMode== DataGridViewTriState.True && this.RowIndex>=0)
        {
            var value= string.Format("{0}", this.FormattedValue);
            using (var g = this.OwningColumn.DataGridView.CreateGraphics())
            {
                var r =  g.MeasureString(value, cellStyle.Font, this.OwningColumn.Width )
                          .ToSize();
                r.Width += cellStyle.Padding.Left + cellStyle.Padding.Right;
                r.Height += cellStyle.Padding.Top + cellStyle.Padding.Bottom;
                return r;
            }
        }
        else
        {
            return base.GetPreferredSize(graphics, cellStyle, rowIndex, constraintSize);
        }
    }
    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)
    {
        base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, 
            formattedValue, errorText, cellStyle, advancedBorderStyle, 
            paintParts & ~ DataGridViewPaintParts.ContentForeground);
        graphics.DrawString(string.Format("{0}", formattedValue), 
            cellStyle.Font, Brushes.Black, cellBounds);
    }
}

Example

public class Model
{
    public string Text { get; set; }
}

BindingList<Model> list = new BindingList<Model>();

private void Form1_Load(object sender, EventArgs e)
{
    var column1 = new DataGridViewTextBoxColumn();
    column1.CellTemplate = new MyDataGridViewTextBoxCell();
    column1.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
    column1.DataPropertyName = "Text";
    column1.DefaultCellStyle = new DataGridViewCellStyle();
    column1.DefaultCellStyle.WrapMode = DataGridViewTriState.True;
    column1.HeaderText = "Text";
    column1.Name = "column1";

    dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;
    dataGridView1.Columns.Add(column1);

    this.dataGridView1.DataSource = list;
}

private void button1_Click(object sender, EventArgs e)
{
    list.Add(new Model() { Text = textBox1.Text });
}
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398