サイズが不明なCollectionをDataGridにバインドさせて表示させようとしても思い通りに表示されず、SyncRoot列やIsSynchronized列が表示されてしまいます。
その解決策を紹介します。
サイズ(Collectionの列数)が未定だからと言って、XAMLに大量の<DataGrid.Columns/>を記述するのも見栄えが悪いし、そもそも記述しきれないことが多そうなのでそれを回避する方法です。
サイズ不明なコレクションをDataGridに表示するケース
どのようなケースでサイズ未定なコレクションをDataGrid表示したいと思うのでしょうか?
例えば、読み取ったcsvファイルに含まれるデータ群をGUIに表示したいケースなどが考えられますね。
読み取るcsvファイルの列数が不明な場合は本手法が役に立つと思います。
失敗例:DataGridにCollectionをバインドした場合
ここではCollection<double[]>(10行×10列)を使用しています。
特に考えずにDataGridにCollectionをバインドした場合、以下のように表示されます。

コレクションの中身が表示さておらず、思い通りの動作ではないです。
<DataGrid.Columns/>を記述する場合は、サイズ(DataGridの列数)が不明なため多めに記述する必要がある。
予測される列数がせいぜい20列くらいならまだしも、
それより多い場合、<DataGrid.Columns/>を大量に記述することになってしまう。
解決策:Collectionと同等なDataTableを作成してバインド
どうやらCollectionをうまく活用しても今回の目的は達成できないようです。
そこでCollectionと同じ中身を持つDataTableを作成し、それとバインドすることで簡単に表示できました。
以下はCollectionをDataTableに変換し、返すメソッドを含むViewModelである。
public MainViewModel()
{
//コレクションを作成
myCollection = new Collection<double[]>
{
new double[]{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
new double[]{ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 },
new double[]{ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 },
new double[]{ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39 },
new double[]{ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49 },
new double[]{ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59 },
new double[]{ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69 },
new double[]{ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79 },
new double[]{ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89 },
new double[]{ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 }
};
//Collectionと同じ中身のDataTableを作成
myDataTable = new DataTable();
myDataTable = CollectionToDataTable(myCollection);
}
//CollectionをDataTable化して表示するためのメソッド
public DataTable CollectionToDataTable(Collection<double[]> coll)
{
DataTable dt = new DataTable() { };
//列ヘッダの生成+列数の取得
for(int i = 1; i <= coll[0].Length; i++)
{
dt.Columns.Add(i.ToString());
}
//各行にコレクションの情報を入れる
for(int i = 0; i < coll.Count; i++)
{
//一行分の文字配列
string[] row_str = new string[] { };
for(int j = 0; j <= coll[0].Length - 1; j++)
{
//配列の長さを一つ伸ばす(末尾に追加できるようにする)
row_str.CopyTo(row_str = new string[row_str.Length + 1], 0);
//追加された末尾に要素を追加
row_str[row_str.Length - 1] = coll[i][j].ToString();
}
//テーブルに追加
dt.Rows.Add(row_str);
}
return dt;
}
XAMLは以下の通り。
<DataGrid AutoGenerateColumns="True" Margin="20"
ItemsSource="{Binding myDataTable}"/>
実行結果を以下画像に示します。

無事表示できました。
列ヘッダを表示できるところがよいですね。


コメント