C#のWPFでDataGridのヘッダーに値をバインドする

C#のWPFで表形式のデータを表示するDataGridコントロール。

XAMLを編集してデザインなどかなり自由にカスタマイズできます。
ヘッダーをカスタマイズして合計を表示させたいと思う事も出てくるかもしれません。

そして、合計の値を動的に変更したい場合はデータをバインドと思う事でしょう。


DataGridのヘッダーに値をバインド

サンプルとして以下のようなDataGridを作成してみました。

ヘッダーをカスタマイズして合計や最小・最大・平均を表示させる想定です。

バインドさせるデータクラスの定義

ヘッダーにバインドさせるためのデータクラスを以下のように定義しました。

合計・最大・最小・平均の各値を持つクラスです。

    public class TestHeader : INotifyPropertyChanged
    {
        private int _Total;
        private int _Min;
        private int _Max;
        private int _Average;

        public int Total
        {
            get { return _Total; }
            set { _Total = value; OnPropertyChanged("Total"); }
        }
        public int Min
        {
            get { return _Min; }
            set { _Min = value; OnPropertyChanged("Min"); }
        }
        public int Max
        {
            get { return _Max; }
            set { _Max = value; OnPropertyChanged("Max"); }
        }
        public int Average
        {
            get { return _Average; }
            set { _Average = value; OnPropertyChanged("Average"); }
        }
      
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string name)
        {
            if (null == this.PropertyChanged) return;
            this.PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
    }

バインドするデータをDataContextへセット

データオブジェクトを作成したら、ウィンドウのDataContextへセットします。

    public partial class TestWindow1 : Window
    {
        public TestWindow1()
        {
            var header = new TestHeader();
            header.Total   = 110;
            header.Min     =  10;
            header.Max     = 100;
            header.Average =  55;

            InitializeComponent();
            DataContext = header;
        }
    }

XAMLの定義

<Window x:Class="WpfTest1.TestWindow1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfTest1"
        mc:Ignorable="d"
        Title="TestWindow1" Height="300" Width="350">
    <StackPanel Margin="20">
        <DataGrid AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.Header>
                        <StackPanel Margin="5,2" Width="100">
                            <TextBlock Text="項目"/>
                        </StackPanel>
                    </DataGridTemplateColumn.Header>
                </DataGridTemplateColumn>
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.Header>
                        <Grid Margin="5,2">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="Auto"/>
                            </Grid.ColumnDefinitions>
                            <TextBlock Grid.Column="0" Margin="10,0" VerticalAlignment="Center" Text="金額"/>
                            <Grid Grid.Column="1" Margin="2,0">
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="Auto"/>
                                    <RowDefinition Height="Auto"/>
                                    <RowDefinition Height="Auto"/>
                                    <RowDefinition Height="Auto"/>
                                </Grid.RowDefinitions>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="Auto"/>
                                    <ColumnDefinition Width="Auto"/>
                                </Grid.ColumnDefinitions>
                                <TextBlock Grid.Row="0" Grid.Column="0" Text="合計:" Foreground="Gray"/>
                                <TextBlock Grid.Row="1" Grid.Column="0" Text="最小:" Foreground="Gray"/>
                                <TextBlock Grid.Row="2" Grid.Column="0" Text="最大:" Foreground="Gray"/>
                                <TextBlock Grid.Row="3" Grid.Column="0" Text="平均:" Foreground="Gray"/>
                                <TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Path=DataContext.Total,   RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" HorizontalAlignment="Right"/>
                                <TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Path=DataContext.Min,     RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" HorizontalAlignment="Right"/>
                                <TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Path=DataContext.Max,     RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" HorizontalAlignment="Right"/>
                                <TextBlock Grid.Row="3" Grid.Column="1" Text="{Binding Path=DataContext.Average, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" HorizontalAlignment="Right"/>
                            </Grid>
                        </Grid>
                    </DataGridTemplateColumn.Header>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </StackPanel>
</Window>

42~45行目で値をバインドしています。

BindingのPathには DataContext を参照するようにしています。

さらにRelativeSourceを設定してWindowクラスを指定します。