格式化DataGridView单元格而不更改基础值?

I have an unbound DataGridView (in VS 2008), of which one column contains a file path. I'd like to format the string using the TextRenderer class on the ColumnWidthChanged event without actually modifying the underlying value. The problem is that the contents of the table are saved when the form is closed and I don't want to save the formatted value. I think I'm just in too deep to see the obvious solution so I'm depending on you guys to point it out :-).

The idea is to display this:

C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\gacutil.exe

...as this (depending on the width of the column):

C:\Program Files\Microso…\gacutil.exe


It appears I spoke too soon. I'm getting some very strange results from TextRenderer.MeasureText(). If I hardcode the path value as "C:\Documents and Settings\jluce\My Documents\Downloads" it comes ends up as C:\Documents and Settings\jluce\M...\Downloads\0wnloads". If I don't hardcode it (like below) it gets further corrupted each time I resize the column.

Here's what it looks like after a couple resizes: Screenshot

Here's what I'm currently doing.

  if (e.ColumnIndex == 1)
  {
    foreach (DataGridViewRow Row in mappingsDataGrid.Rows)
    {
      string Path = (string)Row.Cells[1].Value;
      Path = Path.Trim();

      TextRenderer.MeasureText(Path, e.CellStyle.Font,
        new Size(mappingsDataGrid.Columns[e.ColumnIndex].Width, Row.Height),
          TextFormatFlags.ModifyString | TextFormatFlags.PathEllipsis);

      e.Value = Path;
    }
  }

This just keeps getting weirder!!

I managed to fix the problem of the mangled string by iterating through each char and removing the bad ones. However, now I've got an even crazier problem. A local variable I'm assigning in the event handler is retaining its value between calls.

Here's the relevant code:

     string Path = ""; // <-- #1
     Path = "C:\\Documents and Settings\\jluce\\My Documents\\Downloads"; // <-- #2

      TextRenderer.MeasureText(Path, Row.Cells[1].Style.Font,
        new Size((mappingsDataGrid.Columns[e.Column.Index].Width), Row.Height),
          TextFormatFlags.ModifyString | TextFormatFlags.PathEllipsis);

      // Left out code that strips invalid chars

      Row.Cells[1].Value = Path; // <-- #3
      Path = null;

First time resizing column (refer to #'s in the comments above):

  1. After this line Path contains "".
  2. After this line Path contains string just as it appears above.
  3. Path contains truncated file path as it should (i.e. "C:\Documents and Setti...\Downloads")

Second time resizing:

  1. After this line Path contains "", as it should.
  2. After this line Path contains "C:\Documents and Set...\Downloads\0 Documents\Downloads", which was the invalid value from the previous iteration before I stripped out the invalid characters (seen here as '\0')!!
  3. Now the path is FUBAR because I started with a screwed up string and it just keeps getting worse.

Why would Path be assigned the invalid value from the previous function call (after correctly assigning an empty string!) when I'm explicitly assigning a value to it?!!!!!

#0

You need to use CellFormatting event to CHANGE the given value before it's printed (the original object value won't be modified). In your case, you could check if it's the right column by verifying e.ColumnIndex variable and change the e.Value text as I did below:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        dataGridView1.DataSource = new List<Person>(new Person[] { new Person() { Name = "André", Adress = "Brazil" } });
    }

    private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
    {
        e.Value = e.Value + " modified";
    }
}

class Person
{
    public String Name { get; set; }
    public String Adress { get; set; }
}

#1

TextRenderer.MeasureText method is a nasty one -- it changes the actual string passed as parameter, so it's changing the actual string referenced by the DataGridView. It actually makes a .Net string mutable.

It also seems that this ridiculous method doesn't change the actual Length of the string, but merely overwrites one of the characters with \0 to indicate the end of the string (like null-terminated strings in plain C). That's some funny stuff!

This can have a serious impact on the stability of your app. If you take into account that .Net uses string interning, you can start getting all sorts of weird results, as you did notice that your string constants no longer seem constant.

First step is to create a copy of your string (a new instance with same characters):

string Path = String.Copy(e.Value as string ?? "");

instead of

string Path = (string)Row.Cells[1].Value;

This will ensure that no matter what TextRenderer does, original string will remain unchanged.

After that, you need to get rid of the null-character in the modified string.

By doing this:

if (Path.IndexOf('\0') >= 0)
   e.Value = Path.Substring(0, Path.IndexOf('\0'));
else
   e.Value = Path;

you will create a new instance of a clean, modified string (leaving our temporary Path copy unreferenced for garbage collection).

推荐文章

分析IMAP时,base64编码的字符串通过fgets调用被截断

分析IMAP时,base64编码的字符串通过fgets调用被截断

推荐文章

Zend_Log_Writer_Firebug()不工作

Zend_Log_Writer_Firebug()不工作

推荐文章

如何在android设备旋转时保留警报对话框

如何在android设备旋转时保留警报对话框

推荐文章

如何在C++中打印字符串

如何在C++中打印字符串

推荐文章

SQL函数中的两个日期参数

SQL函数中的两个日期参数

推荐文章

错误android.view.InflateException,无法对MapView类进行充气

错误android.view.InflateException,无法对MapView类进行充气

推荐文章

less是否必须与指针类型的相等运算符一致?

less是否必须与指针类型的相等运算符一致?

推荐文章

在Sinatra应用程序中使用Rails应用程序的ActiveRecord模型会产生多个警告

在Sinatra应用程序中使用Rails应用程序的ActiveRecord模型会产生多个警告

推荐文章

如何制作标记,以便在单击该标记时,URL不应进入地址栏?

如何制作标记,以便在单击该标记时,URL不应进入地址栏?

推荐文章

JPA/如何以只读模式获取实体?

JPA/如何以只读模式获取实体?

推荐文章

在silverlight中多次调用异步方法问题

在silverlight中多次调用异步方法问题

推荐文章

如何在javascript函数中访问python对象?

如何在javascript函数中访问python对象?

推荐文章

将参数键入变量

将参数键入变量

推荐文章

我可以在Windows 7中使用mono为iPhone开发应用程序

我可以在Windows 7中使用mono为iPhone开发应用程序

推荐文章

JSF不允许通过jquery&javascript生成html标记?

JSF不允许通过jquery&javascript生成html标记?

推荐文章

有一个调用另一个活动的主活动

有一个调用另一个活动的主活动