【发布时间】:2018-10-23 23:05:28
【问题描述】:
我想使用 DataGrid 在 C# 中显示字符串表。列名是动态生成的(即在编译时未知)。
这是一个例子:
在这里,数字已转换为字符串。
我使用 DataTable 作为包含整个表(行和列标题)的 DataGrid 的源。但是,我遇到的问题是“气候变化”列中的值未显示在 DataGrid 中。相反,我在控制台上收到以下错误消息
"BindingExpression path error: 'climate w' property not found on 'object'
''DataRowView' (HashCode=22429696)'. BindingExpression:Path=climate
w/change; DataItem='DataRowView' (HashCode=22429696); target element is
'TextBlock' (Name=''); target property is 'Text' (type 'String')"
我知道这是由于列名中的斜杠(“/”)被解释为绑定表达式。
我的问题是
- 有没有办法关闭该行为,即列名被解释为绑定表达式?由于我提供了一个 DataTable,其中包含行和列的所有值和标题,因此不需要根据列名计算任何数据值。此外,尽管不存在名为 HumanToxicity 的属性,但“人类毒性”列也没有问题。
- 如果我不能使用 DataTable 作为 DataGrid 的源来实现上述目的,那么应该使用哪种数据结构正确?
这是生成数据表的代码。
public DataTable PaValues { get; set; }
private void CreateDataSet()
{
var dt = new DataTable("Perturbation Analysis");
List<String> ics = _perturbationAnalysis.ImpactCatagories();
dt.Columns.Add("Parameters");
foreach (var ic in ics)
{
dt.Columns.Add(Sanatize(ic));
}
foreach (var parameter in _perturbationAnalysis.ParameterNames())
{
var dr = dt.NewRow();
dr[0] = parameter;
for (int i = 0; i < ics.Count; i++)
{
dr[i+1] = _perturbationAnalysis[parameter, ics[i]].ToString();
}
dt.Rows.Add(dr);
}
PaValues = dt;
}
private string Sanatize(string ic)
{
//return ic.Replace("/", "[/]").Replace("[", "").Replace("]", "").Replace(".", " ");
//return "[" + ic + "]";
return ic;
}
这是 XAML 文件的摘录
<DataGrid
x:Name="PAGrid"
CanUserAddRows="False"
CanUserDeleteRows="False"
ClipboardCopyMode="IncludeHeader"
FrozenColumnCount="1"
ItemsSource="{Binding Path=PaValues,UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource DataGridStyle}"
IsReadOnly="True">
</DataGrid>
按照 cmets 中的建议,我添加了一个 AutoGeneratingColumn 处理程序,它将绑定更改为使用方括号:
private void PaViewAutoGeneratingColumnHandler(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
e.Column = new DataGridTextColumn
{
Binding = new Binding("[" + e.Column.Header + "]"), Header=e.Column.Header
};
}
它现在适用于“气候 w/change”,但它不适用于名为“EDIP2003 w/o LT, acidification w/o LT, acidification w/o LT”的列,这是一个真实的例子客户使用。报错信息和之前一样
BindingExpression path error: '[]' property not found on 'object' ''DataRowView' (HashCode=56876317)'.
BindingExpression:Path=[EDIP2003 w/o LT, acidification w/o LT, acidification w/o LT]
【问题讨论】:
-
您可能希望使用 DataGrid 列的
Header属性,而不是 DataTable 中的实际列名。使用这种方法,列名就不会成为问题。 -
将斜线替换为下划线。
-
@Hubert 我一定不清楚。例如,我建议您将列命名为
Col1-ColN,然后使用某种逻辑(映射、列表等)将ColX的Header属性分配给有意义的值,即My/col/header@,保持Binding工作。 -
@AlexSeleznyov 我没有从你的链接中得到它,但我现在尝试了它并且它有效。但它是uuuuugly。我必须使用假列名,然后在视图中修补它们,并从 xaml 文件后面的代码访问视图模型,以访问我必须在视图模型中创建公共属性的真实列名。我很惊讶这样一个简单的问题没有简单的解决方案,但需要破解代码。无论如何,非常感谢大家。我自己无法找到解决方案。
标签: c# wpf datatable binding datagrid