2


0

1つの列にファイルパスが含まれている、バインドされていないDataGridView(VS 2008)があります。 実際に基になる値を変更せずに、ColumnWidthChangedイベントのTextRendererクラスを使用して文字列をフォーマットしたいです。 問題は、フォームが閉じられたときにテーブルの内容が保存され、フォーマットされた値を保存したくないということです。 私は明らかな解決策を見るにはまだ深すぎていると思うので、それを指摘するのはあなた方に頼っています:-)。

アイデアはこれを表示することです:

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

'' '' '

早く話したようです。 私はTextRenderer.MeasureText()から非常に奇妙な結果を得ています。 パス値を「C:¥Documents and Settings¥jluce¥My Documents¥Downloads」としてハードコードすると、C:¥Documents and Settings¥jluce¥M …​¥Downloads¥0wnloadsとなります。 (以下のように)ハードコードしないと、列のサイズを変更するたびにさらに破損します。

カップルのサイズを変更した後の外観は次のとおりです。 Screenshot

これが私が現在やっていることです。

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

TextRenderer.MeasureText(Path、e.CellStyle.Font、新しいサイズ(mappingsDataGrid.Columns [e.ColumnIndex] .Width、Row.Height)、TextFormatFlags.ModifyString | TextFormatFlags.PathEllipsis);

e.Value = Path; }}

'' '' '

これはただ奇妙になり続けています!

私は、各文字を繰り返し処理して悪い文字列を削除することによって、破損した文字列の問題を解決することができました。 しかし、今、私はさらに厄介な問題を抱えています。 イベントハンドラで割り当てているローカル変数は、呼び出し間でその値を保持しています。

関連するコードは次のとおりです。

文字列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);

//無効な文字を取り除くコードを除外

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

コラムのサイズをはじめて変更する(上記のコメント内の#を参照):

  1. この行の後にPathは ""を含みます。

  2. この行の後Pathは、上に表示されているとおりに文字列を含みます。

  3. パスには、切り捨てられたファイルパスが含まれています(つまり、 "C:\ Documents and Setti …​ \ Downloads")

2回目のサイズ変更:

  1. この行の後のPathには、必要に応じて ""が含まれています。

  2. この行の後のパスには "C:\ Documents and Set …​ \ Downloads \ 0 Documents \ Downloads"が含まれています。これは、無効な文字を削除する前の前回の繰り返しからの無効な値です。 !

  3. 私はねじで締められた弦で始めて、そしてそれはただ悪化し続けているので、今道はFUBARです。

明示的に値を代入するときに、Pathに前の関数呼び出しから無効な値が(空の文字列を正しく代入した後に)割り当てられるのはなぜですか?

2 Answer


2


あなたはそれが印刷される前に与えられた値を変えるためにCellFormattingイベントを使う必要があります(オリジナルのオブジェクトの値は変更されません)。 あなたのケースでは、e.ColumnIndex変数を検証することによってそれが正しい列であるかどうかをチェックし、以下のようにe.Valueテキストを変更することができます。

パブリック部分クラスForm1:フォーム{public Form1(){InitializeComponent();} }

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

private void dataGridView1_CellFormatting(オブジェクト送信側、DataGridViewCellFormattingEventArgs e){e.Value = e.Value "modified"; }}

class Person {public String Name {get;};セット; public String Adress {get;}セット; }}


2


`+ TextRenderer.MeasureText +`メソッドはhttp://www.dont-panic.cc/capi/2007/10/03/net-strings-are-not-always-immutable/ [厄介なもの]-を変更しますパラメータとして渡される実際の文字列。したがって、DataGridViewによって参照される実際の文字列を変更しています。 それは実際には.Net文字列を* mutable *にします。

このばかげた方法は、文字列の実際の「+ Length 」を変更せず、単に文字列の終わりを示すために文字の1つを「 \ 0+」で上書きするだけのようです(プレーンのnullで終わる文字列のように) C)。 それは面白いものです!

これはアプリの安定性に深刻な影響を及ぼす可能性があります。 もしあなたが.Netがhttp://msdn.microsoft.com/en-us/library/system.string.intern.aspx[string interning]を使用していることを考慮するなら、あなたがしたように、あなたはいろいろな種類の奇妙な結果を得始めることができますあなたの文字列定数はもはや定数に見えないことに注意してください。

最初のステップはあなたの文字列(同じ文字を持つ新しいインスタンス)のコピーを作成することです。

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

の代わりに

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

これにより、 `+ TextRenderer +`が何をしても、元の文字列が変更されないようになります。

その後、修正された文字列内のnull文字を取り除く必要があります。

こうすることによって:

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

クリーンで変更された文字列の新しいインスタンスを作成します(ガベージコレクションでは参照されない一時的な `+ Path +`コピーを残します)。