WPF DataGridの自動生成

- - posted in wpf | Comments

エンタープライズ系の開発だと表形式のコンポーネントはよく利用されますが、XAMLで表(DataGrid)を書くのがとても面倒なので、自動生成するようにしました。

完成系はこうなります。

wpf-18-01

サンプルはいつものコチラ。

XAMLの世界で見た目は後付でどうにでもなるので、注目するのはCheckBoxやDataPicker、Comboboxなどの 種々のDataGridColumnが自動生成されるところになります。

単純に一つの列を持ち、以下の要件を満たすDataGridを例に挙げます。

  • 列はテキスト列
  • 列ヘッダー中央に表示
  • セルの文字も中央表示
  • セルは読み取り専用

それをXAMLで記述するとこうなります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

<DataGrid>
    <DataGrid.Columns>
        <DataGridTextColumn x:Name="IdentityColumn"
                            Width="100"
                            IsReadOnly="True"
                            Binding="{Binding Path=Identity}" >
            <DataGridTextColumn.Header>
                <DataGridColumnHeader Content="Text Column" VerticalContentAlignment="Center" HorizontalContentAlignment="Center"/>
            </DataGridTextColumn.Header>
            <DataGridTextColumn.ElementStyle>
                <Style TargetType="{x:Type TextBlock}">
                    <Setter Property="TextAlignment" Value="Center" />
                </Style>
            </DataGridTextColumn.ElementStyle>
        </DataGridTextColumn>
    </DataGrid.Columns>
</DataGrid>

データを入れて表示してみます。

wpf-18-02

列のヘッダーのコンテンツに文字(String)をセットすると、自動でTextBlock化されるところや、 列ヘッダーとは別にセルのスタイルを定義できるところなど、理路整然としていて柔軟なのですが 20列のグリッドでテキスト以外が混じったりすると、XAMLを書くのが面倒になり、作業工数や保守性となると少し考えたくなります。

DataGridのXAMLはDataGrid.Columnsプロパティに、必要なDataGridColumnを宣言していく作業になります。

肝心なことはバインド対象のモデルのプロパティに応じて適切なDataGridColumnが用意できれば良いことになります。

では、モデルのプロパティに対する属性としてみましょう。 最初に表示したサンプルのグリッドのモデルは以下になります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class SampleGridModel
{
    [DataGridColumnAnnotation(10, "Identity", 80d)]
    public string Identity { get; set; }

    [DataGridColumnAnnotation(20, "CheckBox Colmun", 250d, IsReadOnly = false)]
    public bool Check { get; set; }

    [DataGridColumnAnnotation(30, "Numeric Colmun", 250d)]
    public int? Value { get; set; }

    [DataGridColumnAnnotation(40, "DatePicker Colmun", 250d, IsReadOnly = false)]
    public DateTime? Dt { get; set; }

    [DataGridColumnAnnotation(50, "ComboBox Colmun", 250d, IsReadOnly = false, ComboBoxDisplayMemberPath = "Title", ComboBoxItemsSourcePath = "Items")]
    public childClass SelectedText { get; set; }

    public IEnumerable<childClass> Items { get; set; }

    public class childClass
    {
        public int Identity { get; set; }
        public string Title { get; set; }
    }
}

DataGridColumnAnnotation属性をデータソースのプロパティにセットするだけで、自動でグリッドを生成(正しくはDataGrid.Columnsにセット) できれば何十行もXAMLを書かずに済みそうです。

属性とプロパティの情報を合わせれば、典型的な列は作成できそうです。 たとえばboolプロパティであれば、DataGridCheckBoxColumnとし、列名やサイズなどの情報を属性から取得することを検討します。

ただし、DataPickerや柔軟なコンボボックスなど既存の用意されたDataGridColumnだけではサポートできない場合は、 DataGridTemplateColumnを利用します。

DataGridTemplateColumnはその名の通り、DataGridTemplateColumn.CellTemplateプロパティにDataTemplateを 設定できることで、セルに自在なコントロールを表示できるようになります。

Cellに対してDataTemlateが使えるということは、容易で柔軟なカスタマイズが可能になります。 DateTime型のプロパティに対してDatePickerでもいいし、なんらかの属性を元に任意のオブジェクトを表示できます。


Comments