2009-10-22 110 views
2

我有一個未綁定的DataGridView(在VS 2008中),其中一列包含文件路徑。我想在ColumnWidthChanged事件中使用TextRenderer類來格式化字符串,而不實際修改基礎值。問題是表格的內容在表格關閉時保存,我不想保存格式化的值。我想我只是太深,看不到明顯的解決方案,所以我要依靠你們指出:-)。格式化DataGridView單元格而不更改基礎值?

這樣做是爲了顯示此:

C:\ Program Files文件\微軟的Visual Studio 8 \ SDK \ 2.0 \斌\的Gacutil.exe

...因爲這(視列的寬度):

C:\ Program Files文件\ Microso位... \將Gacutil.exe


看來我說話太快了。我從TextRenderer.MeasureText()中得到了一些非常奇怪的結果。如果我將路徑值硬編碼爲「C:\ Documents and Settings \ jluce \ My Documents \ Downloads」,它將以 C:\ Documents and Settings \ jluce \ M ... \ Downloads \ 0wnloads結尾。 「T硬編碼(如下面)它獲取每個I調整列時進一步破壞

這裏是什麼樣子後,一對夫婦的調整大小:。 Screenshot

這裏是目前我在做什麼

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 jus不斷變得怪異!

我設法通過迭代每個字符並刪除壞字符來修復mangled字符串的問題。但是,現在我有一個更瘋狂的問題。我在事件處理程序中分配的局部變量在調用之間保留其值。

下面是相關代碼:

 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; 

第一次調整柱(參見#的上述評論):

  1. 後此行路徑中包含 「」。
  2. 在此行之後Path包含字符串,就像它出現在上面一樣。
  3. Path包含截斷的文件路徑,因爲它應該(即 「C:\ Documents和Setti ... \下載」)

第二次調整:

  1. 後此行路徑中包含 「」 , 正如它應該。
  2. 在此行路徑中包含「C:\ Documents and Settings ... \ Downloads \ 0 Documents \ Downloads」,這是前面迭代的無效值,我將無效字符(在此處顯示爲'\ 0 「)!
  3. 現在路徑是FUBAR,因爲我從一根擰起來的繩子開始,它變得越來越糟。

當我明確地爲它指定一個值時,爲什麼Path會被分配上一個函數調用的無效值(在正確指定空字符串後!)!!!!!

+0

看到我的「答案」下面的問題更具體的細節... – jluce50 2009-10-23 15:39:48

回答

2

TextRenderer.MeasureText方法是nasty one - 它改變了傳遞的實際字符串作爲參數,所以它改變了DataGridView引用的實際字符串。它實際上使.Net字符串可變

似乎這種荒謬的方法並沒有改變字符串的實際Length,而只是用\0來覆蓋其中一個字符來指示字符串的結尾(如普通C中的以空字符結尾的字符串)。這是一些有趣的東西!

這可能會嚴重影響應用程序的穩定性。如果考慮到.Net使用string interning,你可能會開始得到各種奇怪的結果,因爲你注意到你的字符串常量看起來不再是常量。

第一步是創建字符串的副本(與相同字符的新實例):

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

,而不是

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

這將確保無論什麼TextRenderer呢,原來字符串將保持不變。

之後,您需要擺脫修改過的字符串中的空字符。

通過這樣做:

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

您將創建一個乾淨的,修改後的字符串的一個新實例(離開我們的臨時Path副本未引用的垃圾收集)。

+0

會這樣做,但是仍然存在MeasureText會破壞數據的問題。即使我使用硬編碼字符串替換您所指的行,也會發生這種情況。 – jluce50 2009-10-23 16:04:43

+0

謝謝,這似乎工作!我同意,這種方法是一個奇怪的。很少的文檔和非常不可預知的結果。 – jluce50 2009-10-24 14:22:04

2

在打印之前,您需要使用CellFormatting事件來更改給定值(原始對象值不會被修改)。在你的情況,你可以檢查它是否是一個正確的列通過驗證e.ColumnIndex變量和更改e.Value文本和我一樣如下:

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; } 
} 
+0

我有一種感覺,這是一件簡單的事情。謝謝!! – jluce50 2009-10-23 13:13:38

相關問題