【问题标题】:Wrap a row in DataGridView在 DataGridView 中换行
【发布时间】:2016-09-23 12:31:51
【问题描述】:

我正在尝试创建一个聊天机器人。老实说,UI 不是我的强项。我在聊天机器人的后端工作,就像在逻辑部分一样,但为了测试,我需要一个正常工作的 UI。所以,我选择了更容易使用的winforms。我创建了一个单列 DataGridView,所有写在聊天窗口底部文本框中的文本都将显示为 DataGridView 行。 winform被锚定在各个方向增长。因此,当我加载 exe 时,它​​显示为一个微型窗口,当我将其最大化时,DataGridView 部分和文本框会相应增长。

当我键入一个长字符串并且winform没有处于最大化状态时,文本不会被包裹在可见区域的行中。它水平延伸,因此在屏幕上显然不可见。当我最大化窗口时,我可以看到文本。当我给出一个非常长的字符串并最大化窗口时,行中只显示字符串的大部分内容,因为它可以适合屏幕大小。

我想要做什么:我希望文本自动换行,这样,无论我的窗口是最大化还是最小化,我都可以在窗口中以换行的格式看到整个字符串。

我尝试过的:

dataGridView1.DefaultCellStyle.WrapMode = DataGridViewTriState.True;
dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;

【问题讨论】:

  • @Natrium 那个问题指的是一个文本框,这个问题指的是一个datagridview,这是非常不同的。
  • 它适用于我的测试程序。是否可以在某处覆盖 DefaultCellStyle.WapMode?例如,使用 linq 在表单加载中检查这一点; dataGridView1.Rows.SelectMany(row => row.Cells).All(cell => cell.InheritedStyle == DataGridViewTriState.True);
  • 问题是,当单词用空格分隔时,它会换行,但如果它是一个长字符串,则换行不起作用。
  • DataGridViewTextBox 使用断字执行换行。这意味着如果您的文本很长,则中断仅适用于单词的末尾。根据您的要求,自动换行时需要换行。为此,您需要创建一个自定义单元格并执行换行符。

标签: c# .net winforms datagridview


【解决方案1】:

DataGridViewTextBox 使用分词进行换行。这意味着如果您的文本很长,则中断仅适用于单词的末尾。根据您的要求,换行时需要换行。为此,您需要创建一个自定义单元格并以这种方式执行字符换行:

  • 覆盖GetPreferredSize 方法以根据字符换行计算单元格/行的高度。为此,您可以使用Graphics.MeasureString 方法。

  • 覆盖 Paint 方法以使用 Graphics.DrawString 方法绘制带有字符分隔符的包装字符串。

您可以执行以下设置:

  • 要为您的列使用DataGridView 的宽度,您应该将其设置为AutoSizeModeFill。这样,您的列宽将填充网格并根据网格大小更改其大小。此外,如果您有多个列,您可以设置 FillWeight 来控制列大小相对于其他列的百分比。

  • 要将列中的文本换行,应将列的DefaultCellStyle.WrapMode 设置为DataGridViewTriState.True

  • 要使行自动调整大小,您应该将 AutoSizeRowModeDataGridView 设置为 DataGridViewAutoSizeRowsMode.AllCells

  • 将我们创建的自定义单元格注册为列的CellTemplate

MyDataGridViewTextBoxCell

此单元格使用换行符而不是分词符执行文本换行。

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);
    }
}

示例

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 });
}

【讨论】:

  • 太棒了..效果很好。谢谢您的帮助。欣赏它。
猜你喜欢
  • 1970-01-01
  • 2011-09-13
  • 2013-06-12
  • 2010-10-25
  • 1970-01-01
  • 2015-09-10
  • 1970-01-01
  • 2013-07-28
  • 1970-01-01
相关资源
最近更新 更多