C#DataTable DataGrid特殊字符" /"列名

时间:2018-05-14 10:05:27

标签: c# wpf datatable binding datagrid

我想使用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')"

我知道这是由于列名中的斜杠(" /")被解释为绑定表达式。

我的问题是

  1. 有没有办法关闭该行为,即列名被解释为绑定表达式?由于我为DataTable提供了行和列的所有值和标头,因此不需要根据列名计算任何数据值。该栏"人类毒性"虽然不存在名为HumanToxicity的属性,但没有问题。
  2. 如果我不能使用DataTable作为DataGrid的源来实现上述目标,那么这是正确使用的数据结构吗?
  3. 以下是生成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文件的摘录

                <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处理程序,它将绑定更改为使用方括号:

        private void PaViewAutoGeneratingColumnHandler(object sender, DataGridAutoGeneratingColumnEventArgs e)
        {
            e.Column = new DataGridTextColumn
            {
                Binding = new Binding("[" + e.Column.Header + "]"), Header=e.Column.Header
    
            };
        }
    

    它现在适用于&#34;气候变化&#34;但它不适用于名为&#34; EDIP2003没有LT,没有LT的酸化,没有LT的酸化& #34;,这是客户使用的真实示例。错误消息与之前相同

    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] 
    

1 个答案:

答案 0 :(得分:1)

查看PropertyPath syntax上的文档,我们可以了解为什么字符串无法映射。

您已经指出并可以解决的第一个是斜杠/

  

源遍历(绑定到集合层次结构)

<object Path="propertyName/propertyNameX" .../>
     

此语法中的/用于在层次结构数据源对象中导航,并且支持使用连续的/字符进入层次结构的多个步骤。

此问题通过使用索引器([])来解决。

但是,索引器格式支持多个索引器,以逗号分隔:

  

多个索引器

<object Path="[index1,index2...]" .../>
     

<object Path="propertyName[index,index2...]" .../>
     

如果给定对象支持多个索引器,则可以按顺序指定这些索引器,类似于数组引用语法。有问题的对象可以是当前上下文,也可以是包含多索引对象的属性的值。

如果进一步看,我们可以看到可以使用以下语法对逗号进行转义:

  

转义属性路径字符串

     

对于某些业务对象,您可能会遇到以下情况:属性路径字符串需要转义序列才能正确解析。转义的需求应该很少,因为许多这样的字符在通常用于定义业务对象的语言中也存在类似的命名交互问题。

     
      
  • 在索引器([])内,插入号(^)转义了下一个字符。
  •   

使用所有这些,我想出了以下解决方案,以在仍然使用自动生成的列的情况下转义所有内容。可能有些矫kill过正,但它可以确保正确解释字符串。

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,
    };
}