オルタナティブ・ブログ > IT's my business >

IT業界のコメントマニアが始めるブログ。いつまで続くのか?

(XAML#22)「DataGrid と行ヘッダ」

»

DataGrid の左端には細い枠があります。この部分を行ヘッダ(RowHeader)と言います。たとえば、SelectionUnit が FullRow のときは、どのカラムをクリックしても行全体が選択されますが、CellOrRowHeader になっていると、セルをクリックしたときには単一のセルが、この左端の枠をクリックしたときには行全体が選択されます。幅が狭くてクリックしにくい場合は、次のように行ヘッダのテンプレートを独自に設定することで広げることができます。

<DataGrid ...>
    <DataGrid.RowHeaderTemplate>
        <DataTemplate>
            <Rectangle Width="10" />
        </DataTemplate>
    </DataGrid.RowHeaderTemplate>

この行ヘッダに行番号を表示することを考えてみます(上記の RowHeaderTemplate は、削除しておいてください)。これは、それぞれの行データを読み込んだときに、行ヘッダに行番号を設定するだけです。

[XAML]
<DataGrid ...
    LoadingRow="DataGrid_LoadingRow">

[コード]
private void DataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
{
    e.Row.Header = (e.Row.GetIndex() + 1).ToString();
}

データを表示するだけの DataGrid であれば、これで十分ですが、データを追加したり削除するような編集用途の場合には不十分です。データを読み込んだときに表示された行番号は削除されたり、新たなデータが追加された場合に更新されないためです。行の追加や削除を行った場合に、すべての行番号をリフレッシュするプログラムは次のように記述できます。

[XAML]
<DataGrid ...
    LoadingRow="DataGrid_LoadingRow"
    UnloadingRow="DataGrid_UnloadingRow">

[コード]
private void RefreshNumbers(object sender)
{
    var dg = sender as DataGrid;
    if (dg != null)
    {
        foreach (var item in dg.Items)
        {
            var row = (DataGridRow)dg.ItemContainerGenerator.ContainerFromItem(item);
            if (row != null)
                row.Header = (row.GetIndex() + 1).ToString();
        }
    }
}

private void DataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
{
    RefreshNumbers(sender);
}

private void DataGrid_UnloadingRow(object sender, DataGridRowEventArgs e)
{
    RefreshNumbers(sender);
}

データを更新するたびに全レコードを探索しているため、データ量が多い場合はパフォーマンスが悪くなることに注意してください。

Xaml22(ホント大変でした……)

Comment(0)