问题描述
我想使用DataGrid在C#中显示字符串表.列名是动态生成的(即在编译时未知).
I would like to display a table of strings in C# using a DataGrid. The column names are dynamically generated (i.e. not known at compile time).
这里是一个例子:
在这里,数字已转换为字符串.
Here, the numbers have been converted to strings.
我正在使用DataTable作为包含整个表(行和列标题)的DataGrid的源.但是,我有一个问题,即气候变化"列中的值未显示在DataGrid中.相反,我在控制台上收到以下错误消息
I am using a DataTable as the source for the DataGrid which contains the whole table (rows and column headers). However, I have the problem that the values in column "climate w/change" are not shown in the DataGrid. Instead I get the following error message on the Console
"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')"
我知道这是由于列名中的斜杠("/")被解释为绑定表达式.
I understand that this is due to the slash ("/") in the column name which is interpreted as a binding expression.
我的问题是
- 是否可以关闭该行为,即将列名解释为绑定表达式?由于我为DataTable提供了行和列的所有值和标头,因此无需根据列名计算任何数据值.尽管不存在名为HumanToxicity的属性,但人类毒性"一栏也没有问题.
- 如果我不能使用DataTable作为DataGrid的源来实现上述目标,那是要使用的正确数据结构?
这是生成数据表的代码.
Here is the code to generate the DataTable.
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文件的摘录
Here is the excerpt from the XAML file
<DataGrid
x:Name="PAGrid"
CanUserAddRows="False"
CanUserDeleteRows="False"
ClipboardCopyMode="IncludeHeader"
FrozenColumnCount="1"
ItemsSource="{Binding Path=PaValues,UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource DataGridStyle}"
IsReadOnly="True">
</DataGrid>
如评论中所建议,我添加了一个AutoGeneratingColumn处理程序,该处理程序将绑定更改为使用方括号:
As proposed in the comments, I have added an AutoGeneratingColumn handler, which changes the binding to use square brackets:
private void PaViewAutoGeneratingColumnHandler(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
e.Column = new DataGridTextColumn
{
Binding = new Binding("[" + e.Column.Header + "]"), Header=e.Column.Header
};
}
它现在可以很好地用于气候变化",但不适用于名为"EDIP2003 w/o LT,酸化w/o LT,酸化w/o LT"的列,这是一个真实的示例由客户使用.错误消息与以前相同
It now works fine for "climate w/change", but it does not work for a column named "EDIP2003 w/o LT, acidification w/o LT, acidification w/o LT", which is a real life example used by the customer. The error message is the same as before
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]
推荐答案
查看 PropertyPath语法,我们可以看到为什么字符串无法映射.
Looking at the documentation on PropertyPath syntax, we can see why the strings fail to map.
您已经指出并可以解决的第一个是斜线/
:
The first one, which you already pointed out and could fix, is the slash /
:
<object Path="propertyName/propertyNameX" .../>
此语法中的/用于在层次结构数据源对象中导航,并且支持使用连续的/字符进入层次结构的多个步骤.
The / in this syntax is used to navigate within a hierarchical data source object, and multiple steps into the hierarchy with successive / characters are supported.
这是通过使用索引器([]
)修复的.
This is fixed by using an indexer ([]
).
但是,索引器格式支持多个索引器,以逗号分隔:
However, the indexer format supports multiple indexers, separated by comma:
<object Path="[index1,index2...]" .../>
或
<object Path="propertyName[index,index2...]" .../>
如果给定对象支持多个索引器,则可以按顺序指定这些索引器,类似于数组引用语法.有问题的对象可以是当前上下文,也可以是包含多索引对象的属性的值.
If a given object supports multiple indexers, those indexers can be specified in order, similar to an array referencing syntax. The object in question can be either the current context or the value of a property that contains a multiple index object.
如果进一步看,我们可以看到可以使用以下语法对逗号进行转义:
If we look further, we can see that we can escape the comma using the following syntax:
- 在索引器([])内,插入号(^)会跳出下一个字符.
使用所有这些,我想出了以下解决方案,以在仍然使用自动生成的列的情况下对所有内容进行转义.可能有些矫kill过正,但它可以确保正确解释字符串.
Using all of this, I came up with the following solution to escape everything while still using auto-generated columns. It might be overkill, but it guarantees that the string is interpreted correctly.
private void PaViewAutoGeneratingColumnHandler(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
var columnName = (string)e.Column.Header;
// We'll build a string with escaped characters.
// The capacity is the length times 2 (for the carets),
// plus 2 for the square brackets.
// This is not optimized for multi-character glyphs, like emojis
var bindingBuilder = new StringBuilder(columnName.Length * 2 + 2);
bindingBuilder.Append('[');
foreach (var c in columnName)
{
bindingBuilder.Append('^');
bindingBuilder.Append(c);
}
bindingBuilder.Append(']');
e.Column = new DataGridTextColumn
{
Binding = new Binding(bindingBuilder.ToString()),
Header = e.Column.Header,
};
}
这篇关于C#DataTable DataGrid特殊字符"/"列名称中的(斜杠)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!