C#DataGridView:长文本截断为“…”&引用;列右对齐时位于左侧

C#DataGridView:长文本截断为“…”&引用;列右对齐时位于左侧,c#,datagridview,truncate,C#,Datagridview,Truncate,我有一个关于单元格截断的问题(替换为“…”): 当列右对齐时,如何在单元格左侧显示替换“…” 我使用的是非等宽字体,所以我不能仅仅计算字符数来做一些字符串操作作为解决办法,我需要一个解决方案。我相信应该有 为了说明我的问题,我在这里模拟我的DataGridView Left Context (Right aligned column) | Center Word | Right Context (Left aligned column) left c

我有一个关于单元格截断的问题(替换为“…”):

当列右对齐时,如何在单元格左侧显示替换“…”

我使用的是非等宽字体,所以我不能仅仅计算字符数来做一些字符串操作作为解决办法,我需要一个解决方案。我相信应该有

为了说明我的问题,我在这里模拟我的DataGridView

Left Context (Right aligned column)        | Center Word | Right Context (Left aligned column)
                left context not truncated | CenterWord  | Right context not truncated
...Here is the long left context truncated | CenterWord  | Here is the long right context truncated...
我想我已经说清楚了

谢谢。请帮帮我

彼得

注:同样的问题可以在这个链接上找到:

这绝对是一件不寻常的事情,但(和其他任何事情一样)它是可以做到的。这是一个测量字符串大小并将其与单元格大小进行比较的问题。(请注意,我假设数据是由用户输入的。如果要进行数据绑定,基本上必须使用其他事件。)

这可以工作,但可能需要一些微调:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        dataGridView1.Columns.Add("col1", "col1");
        dataGridView1.Columns[0].CellTemplate.Style.Alignment = DataGridViewContentAlignment.MiddleRight;
        dataGridView1.Columns.Add("col2", "col2");
        dataGridView1.Columns.Add("col3", "col3");

        dataGridView1.Rows.Add();
        dataGridView1.CellEndEdit += new DataGridViewCellEventHandler(dataGridView1_CellEndEdit);
        dataGridView1.ColumnWidthChanged += new DataGridViewColumnEventHandler(dataGridView1_ColumnWidthChanged);              
    }

    void dataGridView1_ColumnWidthChanged(object sender, DataGridViewColumnEventArgs e)
    {
        if (e.Column.Index == 0)
        {
            // We need to truncate everything again when the width changes
            foreach (DataGridViewRow row in dataGridView1.Rows)
            {
                RightTruncateText(row.Cells[0]);
            }
        }
    }

    void RightTruncateText(DataGridViewCell cell)
    {                        
        // check if the content is too long:
        using (Graphics g = Graphics.FromHwnd(this.Handle))
        {
            SizeF size = g.MeasureString((string)cell.Tag, dataGridView1.Font); // NOTE: using the tag

            if (size.Width > cell.Size.Width)
            {
                StringBuilder truncated = new StringBuilder((string)cell.Tag);

                truncated.Insert(0, "...");

                // Truncate the string until small enough (NOTE: not optimized in any way!)                        
                while (size.Width > cell.Size.Width)
                {
                    truncated.Remove(3, 1);
                    size = g.MeasureString(truncated.ToString(), dataGridView1.Font);
                }
                cell.Value = truncated.ToString();
            }
            else
            {
                cell.Value = cell.Tag;
            }
        }
    }

    void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
    {
        if (e.ColumnIndex == 0)
        {
            // Save the value in the tag but show the truncated value
            DataGridViewCell cell = dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex];
            cell.Tag = cell.Value; // Saving the actual state
            RightTruncateText(cell);
        }
    }
}

我已经做了一个变通方法,除了“…”(截断效果很好)之外,它还在工作

此解决方案的唯一问题是我不知道如何设置TextFormatFlags以获得所需的正确行为,与
DataGridView.RightToLeft=Yes
时完全相同

如果启用
TextFormatFlags.EndEllipsis
,三个点“…”将出现在左侧,但它会从字符串的右端截断


我不确定要打开
TextFormatFlags
枚举的哪个标志。

我通过创建自己的
DataGridViewLeftCropTextBoxCell
实现了这一点。不幸的是,它使用了许多.NET内部方法

但首先,我让基类绘制背景和边框(如果没有明显的前景,就不画了)

然后测量文本并缩小它,直到它符合值边界

使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Windows.Forms;
使用系统图;
命名空间项目
{
公共类DataGridViewLeftCropTextBoxCell:DataGridViewTextBoxCell
{
/// 
///颜料含量
/// 
/// 
/// 
/// 
/// 
/// 
/// 
/// 
/// 
/// 
/// 
/// 
受保护的覆盖无效绘制(图形图形、矩形剪贴簿、矩形单元格边界、int行索引、DataGridViewElementState单元格状态、对象值、对象格式化值、字符串错误文本、DataGridViewCellStyle单元格样式、DataGridViewAdvancedBorderStyle advancedBorderStyle、DataGridViewPaintParts paintParts)
{
string formattedString=formattedValue作为字符串;
//没什么可画的
if(String.IsNullOrEmpty(formattedString)){
绘制(图形、剪贴簿、单元格边框、行索引、单元格状态、值、格式化值、错误文本、单元格样式、高级边框样式、绘制部件);
返回;
}
//无前景的亲子画
绘制(图形、剪贴簿、单元格边界、行索引、单元格状态、值、格式化值、错误文本、单元格样式、高级边框样式、paintParts&~DataGridViewPaintParts.ContentForeground);
//没有前景?
if((paintParts&DataGridViewPaintParts.ContentForeground)==DataGridViewPaintParts.None){
返回;
}
//计算值边界
矩形边框宽度=边框宽度(advancedBorderStyle);
矩形边界=单元边界;
valBounds.Offset(borderWidths.X,borderWidths.Y);
valBounds.Width-=borderWidths.Right;
valBounds.Height-=borderWidths.Bottom;
bool cellSelected=(cellState和DataGridViewElementStates.Selected)!=0;
//准备文本标志
TextFormatFlags flags=ComputeTextFormatFlagsForCellStyleAlignment(this.DataGridView.RightToLeft==RightToLeft.Yes,cellStyle.Alignment,cellStyle.WrapMode);
如果((flags&TextFormatFlags.SingleLine)!=0){
flags |=TextFormatFlags.EndEllipsis;
}
//准备文本大小
大小s=TextRenderer.MeasureText(图形,
格式化字符串,
cellStyle.Font
);
//文本符合边界,只需附加
如果(s.WidthvalBounds.Width)&&(truncated.Length>5)){
删除(3,1);
formattedString=截断的.ToString();
s=文本渲染器.MeasureText(图形,
格式化字符串,
cellStyle.Font
);
}
TextRenderer.DrawText(图形,
格式化字符串,
cellStyle.Font,
瓦尔邦兹,
cellSelected?cellStyle.SelectionForeColor:cellStyle.ForeColor,
旗帜
);
}
}
}
您还可以创建自己的列类型:

类DataGridViewLeftCropTextBoxColumn:DataGridViewTextBoxColumn
{
公共覆盖DataGridViewCell单元模板
{
获取{返回新的DataGridViewLeftCropTextBoxCell();}
set{base.CellTemplate=value;}
}
}

我从和
TextFormatFlags ComputeTe中借用了文本收缩
    protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e)
    {
        base.OnCellPainting(e);

        if (e.RowIndex >= 0 && e.ColumnIndex >= 0 &&
            CustomRightToLeftColumnNames.Contains(this.Columns[e.ColumnIndex].Name))
        {
            // Method 2:
            e.PaintBackground(e.CellBounds, true);

            if (e.FormattedValue != null)
            {
                TextFormatFlags flags = TextFormatFlags.RightToLeft         |
                                        TextFormatFlags.VerticalCenter      |
                                        TextFormatFlags.Right               |
                                        TextFormatFlags.LeftAndRightPadding;// |
                                        //TextFormatFlags.EndEllipsis;
                TextRenderer.DrawText
                (
                    e.Graphics,
                    e.FormattedValue.ToString(),
                    e.CellStyle.Font,
                    e.CellBounds,
                    e.CellStyle.ForeColor,
                    flags
                );
            }

            e.Handled = true;
        }
    }