HeyCHのブログ

慢性疲労のへいちゃんです

【C#】DataGrid内のTextBlockにスタイルをあてたい

注意:今回の記事の内容では出力にエラーが出てしまいます。


皆さん。DataGrid内の全てのTextBlockのみにスタイルをあてたいってことありますよね。ね、ありますよね。

今回はそう言った皆様の声にお応えすべく、いろいろ試してみました。
そうしたら、ある条件で要求を満たすことができる書き方を見つけました。

まずはDataGridに画像を表示する方法

f:id:HeyCH:20200519004425p:plain
画像用フォルダを作成する
f:id:HeyCH:20200519004609p:plain
フォルダに画像をドラッグ&ドロップ

                <DataGridTemplateColumn Header="Img">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Image Source="img/icon.png"/>←ここは{Binding Source}とかにしてもOK
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>

本題のDataGrid内のTextBlockのみにスタイルをあてる方法

    <Window.Resources>
        <Style TargetType="DataGridCell">
            <Setter Property="TextBlock.Foreground" Value="Red" />
            <Setter Property="TextBlock.ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content.Text}"/>
        </Style>
    </Window.Resources>

なんと、DataGridCellのPropertyにTextBlockを指定することができます。(でも画像とか表示してるとエラーが表示されます)

参考コード

<Window x:Class="TeraDataGridElementStyle.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:TeraDataGridElementStyle"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <Style TargetType="DataGridCell">
            <Setter Property="TextBlock.Foreground" Value="Red" />
            <Setter Property="TextBlock.ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content.Text}"/>
        </Style>
    </Window.Resources>
    <Grid>
        <DataGrid ItemsSource="{Binding DataList}" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding No}" Header="No" />
                <DataGridTextColumn Binding="{Binding Name}" Header="Name" />
                <DataGridTextColumn Binding="{Binding Id}" Header="Id" />
                <DataGridTemplateColumn Header="Img">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Image Source="{Binding Source}"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace TeraDataGridElementStyle {
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window {
        ViewModel vm;
        public MainWindow() {
            InitializeComponent();
            vm = new ViewModel();
            for (int i = 0; i < 100; i++) {
                vm.DataList.Add(new Data { No = i.ToString(), Name = "Name" + i, Id = i.ToString(), Source = "img/icon.png" });
            }
            this.DataContext = vm;
        }
    }
    public class ViewModel : INotifyPropertyChanged {
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string name) {
            if (PropertyChanged!=null)
                PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
        public ObservableCollection<Data> DataList { get; set; } = new ObservableCollection<Data>();
    }
    public class Data {
        public string No { get; set; }
        public string Name { get; set; }
        public string Id { get; set; }
        public string Source { get; set; }
    }
}

エラー内容

System.Windows.Data Error: 40 : BindingExpression path error: 'Text' property not found on 'object' ''ContentPresenter' (Name='')'. BindingExpression:Path=Content.Text; DataItem='DataGridCell' (Name=''); target element is 'DataGridCell' (Name=''); target property is 'ToolTip' (type 'Object')

結論

エラーが出るプロパティはDataGridTextColumn 等で個別に設定してやろう