DataGridのカラムにバインドする


やりたいこと

DataGridのカラムやヘッダーとViewModelをバインドする。

実装

DataGridColumnのようにビジュアルツリーに含まれないUI要素は、DataContextを継承しないためViewModelとバインドできない。

そこで、プロキシを用意し、それを経由してViewModelとバインドする。

プロキシクラス
using System.Windows;

namespace Sample {
    //Freezableを継承する
    public class BindingProxy : Freezable {
        protected override Freezable CreateInstanceCore() 
            => new BindingProxy();

        //依存関係プロパティを定義する
        public static readonly DependencyProperty DataProperty 
            = DependencyProperty.Register(
                nameof(Data),
                typeof(object),
                typeof(BindingProxy),
                new PropertyMetadata(null));

        public object Data {
            get { return (object)GetValue(DataProperty); }
            set { SetValue(DataProperty, value); }
        }
    }
}

使い方

XAML
<Window x:Class="Sample.MainView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:Sample"
        Title="MainView" Height="300" Width="300">
    <Window.Resources>
        <!--プロキシを準備-->
        <local:BindingProxy x:Key="Proxy" Data="{Binding}" />
    </Window.Resources>
    <Grid>
        <DataGrid>
            <DataGrid.Columns>
                <!--プロキシ経由で参照-->
                <DataGridTextColumn Header="{Binding Data.XXX, Source={StaticResource Proxy}}" />
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

補足

実はプロキシ用のクラスを用意しなくても、FrameworkElementで同じことができる。しかし、役割を明確にしたかったので、専用のクラスを用いた。