💬

WPF の DataGrid で特定のデータのセルだけ色を変えたい

2022/11/18に公開

WPF の DataGrid で特定のデータのセルだけ色を変えたいという要望を受けたのでメモがてら記事にしておきます。

前に似たような記事を書いていますが、こちらは行全体の色を変えるものになります。

https://blog.okazuki.jp/entry/20100519/1274273555

やってみよう

ということで名前と年齢を持っただけのシンプルなクラスを DataGrid に表示するところから始めたいと思います。

.NET 7 で WPF アプリのプロジェクトを作って以下のような感じの Person クラスを定義します。

public class Person
{
    required public string Name { get; set; }
    required public int Age { get; set; }
    // 3 の倍数と 3 のつくデータのときに true を返す
    public bool IsAho => Age % 3 == 0 || Age.ToString().Contains("3");
}

次に XAML です。一応デザイナーでも値が確認できるようにデザイン時のデータを設定しておきます。

MainWindow.xaml
<Window x:Class="WpfApp1.MainWindow"
        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:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <DataGrid x:Name="dataGrid" AutoGenerateColumns="False" IsReadOnly="True">
            <d:DataGrid.ItemsSource>
                <x:Array Type="{x:Type local:Person}">
                    <local:Person Name="Tanaka" Age="33" />
                    <local:Person Name="Kimura" Age="83" />
                    <local:Person Name="Inoue" Age="23" />
                    <local:Person Name="Ota" Age="41" />
                </x:Array>
            </d:DataGrid.ItemsSource>
            <DataGrid.Columns>
                <DataGridTextColumn Header="Name" Binding="{Binding Name}" />
                <DataGridTextColumn Header="Age" Binding="{Binding Age}" />
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

これだけでデザイナーでも表示できるのマジで神。

あとはコードビハインドで適当なデータを DataGrid にセットするようにします。

MainWindow.xaml.cs
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        dataGrid.ItemsSource = Enumerable.Range(1, 10)
            .Select(x => new Person
            {
                Name = $"Tanaka {x}",
                Age = 30 + x,
            })
            .ToArray();
    }
}

実行すると以下のような結果になります。

ここに色付けを追加していきます。

色を付けたいのは特定の年齢の列だけなので Age に対する DataGridTextColumn の CellStyle プロパティで条件を判定して色を指定するようにします。
これを XAML で書くと以下のようになります。

MainWindow.xaml
<Window x:Class="WpfApp1.MainWindow"
        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:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <DataGrid x:Name="dataGrid" AutoGenerateColumns="False" IsReadOnly="True">
            <d:DataGrid.ItemsSource>
                <x:Array Type="{x:Type local:Person}">
                    <local:Person Name="Tanaka" Age="33" />
                    <local:Person Name="Kimura" Age="83" />
                    <local:Person Name="Inoue" Age="23" />
                    <local:Person Name="Ota" Age="41" />
                </x:Array>
            </d:DataGrid.ItemsSource>
            <DataGrid.Columns>
                <DataGridTextColumn Header="Name" Binding="{Binding Name}" />
                <DataGridTextColumn Header="Age" Binding="{Binding Age}">
                    <DataGridTextColumn.CellStyle>
                        <!-- ここで IsAho が True のときだけ背景色を設定している -->
                        <Style TargetType="DataGridCell">
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding IsAho}" Value="True">
                                    <Setter Property="Background" Value="LimeGreen" />
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </DataGridTextColumn.CellStyle>
                </DataGridTextColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

この時点でデザイナー上でも色変わってくれているので本当優秀。

実行すると以下のような結果になります。よく考えたら、なんでこの機能実装するのに表示データを 30 代にしてしまったのだろう…。最後のデータが 40 で良かった。

まとめという名の感想

デザイナーは優秀

Microsoft (有志)

Discussion