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

问题描述 投票:3回答:1

我想使用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的源来实现上述,这是正确的数据结构使用?

以下是生成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

        };
    }

它现在适用于“气候变化”,但它不适用于名为“没有LT的EDIP2003,没有LT的酸化,没有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] 
c# wpf datatable binding datagrid
1个回答
1
投票

查看PropertyPath syntax上的文档,我们可以看到字符串无法映射的原因。

第一个,你已经指出并可以修复,是斜线/

Source Traversal (Binding to Hierarchies of Collections)

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

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

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

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

Multiple Indexers

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

要么

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

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

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

Escapes for Property Path Strings

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

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

使用所有这些,我提出了以下解决方案,以便在仍使用自动生成的列时逃避所有操作。它可能有点矫枉过正,但它保证了字符串被正确解释。

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,
    };
}
© www.soinside.com 2019 - 2024. All rights reserved.