列名中的 C# DataTable DataGrid 特殊字符 "/"(斜杠)

标签 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')"

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

我的问题是
  • 有没有办法关闭这种行为,即列名被解释为绑定(bind)表达式?由于我提供了一个 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>
    

    正如评论中所建议的,我添加了一个 AutoGeneratingColumn 处理程序,它将绑定(bind)更改为使用方括号:
        private void PaViewAutoGeneratingColumnHandler(object sender, DataGridAutoGeneratingColumnEventArgs e)
        {
            e.Column = new DataGridTextColumn
            {
                Binding = new Binding("[" + e.Column.Header + "]"), Header=e.Column.Header
    
            };
        }
    

    它现在适用于“climate 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] 
    

    最佳答案

    查看关于 PropertyPath syntax 的文档,我们可以看到为什么字符串无法映射。

    您已经指出并可以修复的第一个是斜杠 / :

    Source Traversal (Binding to Hierarchies of Collections)

    <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.



    这可以通过使用索引器 ([]) 来解决。

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

    Multiple Indexers

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

    or

    <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.



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

    Escapes for Property Path Strings

    For certain business objects, you might encounter a case where the property path string requires an escape sequence in order to parse correctly. The need to escape should be rare, because many of these characters have similar naming-interaction issues in languages that would typically be used to define the business object.

    • Inside indexers ([ ]), the caret character (^) escapes the next character.


    使用所有这些,我想出了以下解决方案来逃避一切,同时仍然使用自动生成的列。这可能是矫枉过正,但它保证字符串被正确解释。
    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 特殊字符 "/"(斜杠),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50327749/

    相关文章:

    c# - 我应该在以下情况下使用锁吗

    c# - Entity Framework 迁移 - 启用 AutoMigrations 以及添加的迁移

    c# - 如何让 Visual Studio 识别 XAML 更改?

    javascript - jQuery Datatables 过滤器位置

    c# - 空引用异常 C#

    c# - c#的免费报告

    c# - 3D空间中的曲线拟合点

    c# - 使用 ReactiveUi 命令显示 Mahapps.Metro 对话框时遇到问题

    c# - NotifyPropertyChanged 和 ContentControl

    jQuery 数据表过滤器定制