#作るもの
DataGridの列ヘッダーをカレンダーみたいに日付表示させて
行ヘッダーに人名、セルに○とかを表示させるものを考えた
##Model
まずModel
public class Model
{
public DataTable _DataTable { get; set; } = new DataTable();
public int _Year { get; set; } = 2017;
public int _Month { get; set; } = 1;
public Model()
{
string[] lName = {"伊藤","山本","佐藤","鈴木","佐々木","田中","宮本","神谷","池田","岡本" };
string[] fName = {"大輔","太郎","正和","一郎","聡","豊","徹","涼介","人志","将人" };
string[] State = { "-", "△", "◯", "✕" };
Random random = new Random();
_DataTable.Columns.Add("RowHeader");
for (int i = 1; i < DateTime.DaysInMonth(_Year,_Month); i++)
{
_DataTable.Columns.Add(i.ToString());
}
for (int i = 0; i < 20; i++)
{
var row = _DataTable.NewRow();
for (int j = 0; j < _DataTable.Columns.Count; j++)
{
if (j == 0)
{
row[j] = lName[random.Next(lName.Length)] + fName[random.Next(fName.Length)];
}
else
{
row[j] = State[random.Next(State.Length)];
}
}
_DataTable.Rows.Add(row);
}
}
}
DataTableの最初の列には人名を入れるため
_DataTable.Columns.Add("RowHeader");
としている
あとは指定年月の日数分DataTableに列を追加している
んでRowとCellには配列からランダムに値を入れている
サンプルとかでもこういう遊びがほしくなる('ω')
##ViewModel
いつものViewModelだよ
public class ViewModel
{
public Model _Model { get; } = new Model();
}
##View
ここがなかなかややこしいポイント
<DataGrid x:Name="myDataGrid" ItemsSource="{Binding _Model._DataTable}" CanUserReorderColumns="False" CanUserSortColumns="False" CanUserAddRows="False" CanUserDeleteRows="False" AutoGeneratingColumn="myDataGrid_AutoGeneratingColumn">
<DataGrid.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="TextBlock.TextAlignment" Value="Center"/>
</Style>
</DataGrid.CellStyle>
<DataGrid.ColumnHeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="HorizontalContentAlignment" Value="Center"/>
</Style>
</DataGrid.ColumnHeaderStyle>
<DataGrid.RowHeaderStyle>
<Style TargetType="{x:Type DataGridRowHeader}">
<Setter Property="Content" Value="{Binding [0]}"/>
</Style>
</DataGrid.RowHeaderStyle>
</DataGrid>
まずDataGrid.CellStyle
ここではStyleでCellないのTextが中央に表示されるようにしている
列の幅を変えても中央に表示されるよ(゚∀゚)
んでDataGrid.ColumnHeaderStyle
ここでも設定しているのはセルと同じこと
ヘッダー内の文字が中央にくるようにしている
最後にDataGrid.RowHeaderStyle
これがキモ
Styleを使ってDataGridRowHeaderに渡されるデータの最初の列をバインドしている
しかし、AutoGenerateColumnsがTrueなのでこれを実行するとこうなる
まあ当然だよね
そこで、AutoGeneratingColumnイベントで1列目の列生成だけキャンセルすることにする
private void myDataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
if (e.PropertyName == "RowHeader")
{
e.Cancel = true;
}
}
これもcounterみたいなのを作ってindexで判定すると汎用性が上がると思う
#まとめ
最初はDataGridに行列の数が不確定なコレクションを表示させたくていろいろ調べた結果こうなった
これだとDataTable側をいじればDataGrid側をいじる必要がなくなるから便利
あとはReactivePropertyとか使ってデータの操作とかもしてみたい