DOBON.NETプログラミング道掲示板
(現在 過去ログ5 を表示中)
HOME
HELP
新規作成
新着記事
トピック表示
発言ランク
ファイル一覧
検索
過去ログ
[
最新記事及び返信フォームをトピックトップへ
]
[ トピック内全6記事(1-6 表示) ] <<
0
>>
■34848
/ inTopicNo.1)
DataTableのDataRowVersion毎のInt型値の比較がうまくいかない
▼
■
□投稿者/ 奥琵琶湖
一般人(1回)-(2021/07/27(Tue) 09:06:57)
環境/言語:[C#]
分類:[.NET]
DataTableをバインドしたDatagridviewのセルのスタイルを、値の状態によって変更しています。
値に変更があるときは文字色を青色に変更したいので、以下のコードをDatagridview1のCellFormattingのイベントハンドラに書いています。
DataTable1はDatagridview1にバインドしています。DataTable1は数値列と文字列を持っています。
DataRow dtrow = DataTable1.Rows[e.RowIndex];
if (dtrow.RowState == DataRowState.Modified
&& dtrow[e.ColumnIndex, DataRowVersion.Original] != dtrow[e.ColumnIndex,DataRowVersion.Current])
{
e.CellStyle.ForeColor = Color.Blue;
}
dtrow[e.ColumnIndex]の値がstring型の場合は想定通りの動きをするのですが、int型の場合はなぜか常にdtrow[e.ColumnIndex, DataRowVersion.Original] != dtrow[e.ColumnIndex,DataRowVersion.Current]がTrueになります。
そのため、行の他の値に変更があると、数値列は変更がなくても青色に変わってしまいます。
dtrow[e.ColumnIndex, DataRowVersion.Original]とdtrow[e.ColumnIndex, DataRowVersion.Current]の値と型をConsoleに書き出して同じ値になっていても、上記式がTrueになります。
Tostring()してからの比較に書き換えることで、とりあえず回避はできたのですが、なぜこういう動きになるのか理解できません。
if (dtrow.RowState == DataRowState.Modified
&& dtrow[e.ColumnIndex, DataRowVersion.Original].ToString() != dtrow[e.ColumnIndex,DataRowVersion.Current].ToString())
どなたかお分かりでしたら、原因をご教授いただけませんか。よろしくお願いいたします。
引用返信
削除キー/
編集
削除
■34850
/ inTopicNo.2)
Re[1]: DataTableのDataRowVersion毎のInt型値の比較がうまくいかない
▲
▼
■
□投稿者/ 魔界の仮面弁士
大御所(1378回)-(2021/07/27(Tue) 10:53:17)
■
No34848
に返信(奥琵琶湖さんの記事)
> 値に変更があるときは文字色を青色に変更したいので、
これでどうでしょう。
private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
var dgv = (DataGridView)sender;
var col = dgv.Columns[e.ColumnIndex];
var row = dgv.Rows[e.RowIndex];
DataRow dtrow = (row.DataBoundItem as DataRowView)?.Row;
if (!col.IsDataBound || dtrow?.RowState != DataRowState.Modified)
{
return;
}
object oldValue = dtrow[col.DataPropertyName, DataRowVersion.Original];
object curValue = dtrow[col.DataPropertyName, DataRowVersion.Current];
if (oldValue?.GetType() != curValue.GetType() || System.Collections.Comparer.Default.Compare(oldValue, curValue) != 0)
{
// 文字色が黒→青の変化だけだと、違いが分かりにくいのと、
// 文字色だけでは「空文字列にした場合」と「セル選択時」の問題があるので
// 背景色や選択色も合わせて変更しています。
e.CellStyle.ForeColor = Color.Red;
e.CellStyle.BackColor = Color.LightBlue;
e.CellStyle.SelectionForeColor = Color.Yellow;
e.CellStyle.SelectionBackColor = Color.DarkBlue;
}
}
> Datagridview1にバインドしています
dataGridView1 でも
DataGridView1 でもなく、
Datagridview1 表記というのは珍しいですね。
> が Trueになります。
C# なので、普通は True ではなく true と書く所ですね。
bool.TrueString は "True" を返すので、True 表記でも間違いとは言えませんが。
> Int型値の比較がうまくいかない
C# なので、普通は int あるいは Int32 と書く所ですね。
VB 開発者が相手なら、大文字小文字の違いは無視されるので構いませんが、
C# や JavaScript は区別する言語なので、正しく書き分けましょう。
> Tostring()してからの比較に書き換えることで、
Tostring() ではなく
ToString() ですよね。
文字列による比較を用いる場合、「同じ値を示す別の文字列」が
異なる値と見做される可能性がある点に注意してください。
具体的には、「DBNull と空文字列」や「小数値同士」などです。
decimal d1 = 1.00M;
decimal d2 = 1.0M;
// false
bool a = d1.ToString() == d2.ToString();
// true
bool b = d1 == d2;
bool c = System.Collections.Comparer.Default.Compare(d1, d2) == 0;
> DataRow dtrow = DataTable1.Rows[e.RowIndex];
上記の取得方法はお奨めしません。
DataGridView 上の行の並びと、DataTable 上の行の並びは必ずしも一致しないからです。
具体的には、DataGridView の列ヘッダークリックによるソート処理や、
DataView や BindingSource によるフィルター処理を伴った場合ですね。
そのため、バインド元の DataRow を得る場合には、
DataRow dtrow = (((DataGridView)sender).Rows[e.RowIndex].DataBoundItem as DataRowView)?.Row;
のようにした方が確実です。
これは列に対してもいえる事です。
e.ColumnIndex が必ずしも DataTable 上の列番号と一致するわけではありません。
同じ列を書式をかえて複数の列にバインドしたり、一部の列をバインドしなかったり、
バインドしない列を追加することもあるからです。
> dtrow[e.ColumnIndex, DataRowVersion.Original] != dtrow[e.ColumnIndex,DataRowVersion.Current]
これが期待動作しないのは、比較式の両辺が object 型であることが原因です。
object o1 = 1;
object o2 = 1;
// false
bool a = o1 == o2;
bool b = object.ReferenceEquals(o1, o2);
// true
bool c = object.Equals(o1, o2);
bool d = int.Equals(o1, o2);
bool e = (dynamic)o1 == (dynamic)o2;
bool f = System.Collections.Comparer.Default.Compare(o1, o2) == 0;
引用返信
削除キー/
編集
削除
■34851
/ inTopicNo.3)
Re[2]: DataTableのDataRowVersion毎のInt型値の比較がうまくいかない
▲
▼
■
□投稿者/ 奥琵琶湖
一般人(2回)-(2021/07/27(Tue) 11:38:28)
■
No34850
に返信(魔界の仮面弁士さんの記事)
魔界の仮面弁士様
ご丁寧な説明をありがとうございます。また、表記の間違いが多く申し訳ありませんでした。
希望通りの動きを実現できました。
DataGridViewとDataTableの列行ずれの問題も、気になっていたのでご指摘いただき大変助かりました。
(対処療法的に別関数を挟んで変換していました)
ありがとうございました。
引用返信
削除キー/
編集
削除
■34852
/ inTopicNo.4)
Re[3]: DataTableのDataRowVersion毎のInt型値の比較がうまくいかない
▲
▼
■
□投稿者/ 奥琵琶湖
一般人(4回)-(2021/07/27(Tue) 11:44:11)
解決済みを押し忘れました。ありがとうございました。
解決
済
み!
引用返信
削除キー/
編集
削除
■34853
/ inTopicNo.5)
Re[2]: DataTableのDataRowVersion毎のInt型値の比較がうまくいかない
▲
▼
■
□投稿者/ 魔界の仮面弁士
大御所(1379回)-(2021/07/27(Tue) 14:48:59)
■
No34850
に訂正(魔界の仮面弁士の記事)
> 文字列による比較を用いる場合、「同じ値を示す別の文字列」が
> 異なる値と見做される可能性がある点に注意してください。
> 具体的には、「DBNull と空文字列」や「小数値同士」などです。
済みません、ここの説明がおかしいですね。
decimal の例は「同じ値として扱われるが、別の文字列となる」パターンで
DBNull と空文字列は「異なる値であるが、同じ文字列となる」パターンです。
その他、object 型同士の比較の場合、
(byte)0 と (int)0 を同一視するかどうかとか、
"" と null と DBNull を同一視するかどうかといった問題もありえます。
# 今回のケースでは気にする必要が無さそうなので、
# 解決済みチェックはつけたままにしておきます。
解決
済
み!
引用返信
削除キー/
編集
削除
■34854
/ inTopicNo.6)
Re[3]: DataTableのDataRowVersion毎のInt型値の比較がうまくいかない
▲
▼
■
□投稿者/ 奥琵琶湖
一般人(5回)-(2021/07/27(Tue) 16:01:37)
■
No34853
に返信(魔界の仮面弁士さんの記事)
魔界の仮面弁士様
詳細なご説明をありがとうございます。
今回の場合は数値列の値はint型かつ必ず0以上の値が入るので回避できそうです。
ありがとうございました。
解決
済
み!
引用返信
削除キー/
編集
削除
トピック内ページ移動 / <<
0
>>
このトピックに書きこむ
過去ログには書き込み不可
Mode/
通常管理
表示許可
Pass/
HOME
HELP
新規作成
新着記事
トピック表示
発言ランク
ファイル一覧
検索
過去ログ
-
Child Tree
-