WPFのDataGridにDataTable型のプロパティをバインドしたときにセルに値が表示されない事象に遭遇しました。
以下、原因についてメモです。
こんな感じで列のヘッダがファイル名となる表を作ろうとしたのですが、ご覧のとおりうまく表示されませんでした。
バインドエラーを見てみると、拡張子を除いたファイル名がバインドパスになっています。ピリオドが入っているとこうなるんですね。
ためしにファイル名のピリオドをカンマに置き換えてみると・・
うまくいきました(ファイル名はランダムなのでさっきの例と異なります)。
(XAMLバインドエラーを見逃しててデバッグに結構な時間を費やしてしまいました・・)
検証用コード
ViewModel.cs
using System; using System.Collections.Generic; using System.Data; using System.Diagnostics; using System.IO; using System.Linq; namespace DataGridTest { internal class ViewModel { public DataTable Error { get; } public DataTable OK { get; } private (IEnumerable<string>, IEnumerable<IEnumerable<object>>) MakeData() { var random = new Random(0); // 列見出しはランダムなファイル名 var columns = Enumerable.Range(0, 5).Select(_ => Path.GetRandomFileName()); // データ本体はランダムな数値を文字列化したものにします var rows = Enumerable.Range(0, 10).Select(_ => columns.Select(_ => random.Next(0, 100).ToString())); return (columns, rows); } public ViewModel() { (var columns, var rows) = MakeData(); // うまくいかないパターン Error = new DataTable(); _ = Error.Columns.Add("index", typeof(int)); // 列見出しはファイル名をそのままAddします Error.Columns.AddRange( columns.Select(n => new DataColumn(n, typeof(string))).ToArray()); foreach ((var row, var index) in rows.Select((r, i) => (r,i))) { var l = new List<object> { index }; l.AddRange(row); _ = Error.Rows.Add(l.ToArray()); } // うまくいくパターン OK = new DataTable(); _ = OK.Columns.Add("index", typeof(int)); // 列見出しはファイル名のピリオドをカンマに置き換えてAddします OK.Columns.AddRange( columns.Select(n => new DataColumn(n.Replace(".", ","), typeof(string))).ToArray()); foreach ((var row, var index) in rows.Select((r, i) => (r, i))) { var l = new List<object> { index }; l.AddRange(row); _ = OK.Rows.Add(l.ToArray()); } } } }
XAML
<Window x:Class="DataGridTest.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:DataGridTest" mc:Ignorable="d" Title="DataGridTest" SizeToContent="WidthAndHeight"> <Window.DataContext> <local:ViewModel/> </Window.DataContext> <Window.Resources> <Style TargetType="DataGrid" BasedOn="{StaticResource {x:Type DataGrid}}"> <Setter Property="CanUserAddRows" Value="False"/> </Style> <Style TargetType="TextBlock"> <Setter Property="Margin" Value="5"/> </Style> </Window.Resources> <StackPanel> <TextBlock>Error</TextBlock> <DataGrid ItemsSource="{Binding Error}"/> <TextBlock>OK</TextBlock> <DataGrid ItemsSource="{Binding OK}"/> </StackPanel> </Window>