带点的 DataTable 列名称是啥导致它们不适合 WPF 的 DataGrid 控件?

Posted

技术标签:

【中文标题】带点的 DataTable 列名称是啥导致它们不适合 WPF 的 DataGrid 控件?【英文标题】:What is it about DataTable Column Names with dots that makes them unsuitable for WPF's DataGrid control?带点的 DataTable 列名称是什么导致它们不适合 WPF 的 DataGrid 控件? 【发布时间】:2011-02-25 19:19:20 【问题描述】:

运行它,然后感到困惑:

<Window x:Class="Data_Grids.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <DataGrid
        Name="r1"
              ItemsSource="Binding Path=.">
        </DataGrid>
        <DataGrid
        Name="r2"
              ItemsSource="Binding Path=.">
        </DataGrid>
    </StackPanel>
</Window>

代码隐藏:

using System.Data;
using System.Windows;

namespace Data_Grids

    public partial class MainWindow : Window
    
        public MainWindow()
        
            InitializeComponent();

            DataTable dt1, dt2;
            dt1 = new DataTable();
            dt2 = new DataTable();
            dt1.Columns.Add("a-name", typeof(string));
            dt1.Columns.Add("b-name", typeof(string));
            dt1.Rows.Add(new object[]  1, "Hi" );
            dt1.Rows.Add(new object[]  2, "Hi" );
            dt1.Rows.Add(new object[]  3, "Hi" );
            dt1.Rows.Add(new object[]  4, "Hi" );
            dt1.Rows.Add(new object[]  5, "Hi" );
            dt1.Rows.Add(new object[]  6, "Hi" );
            dt1.Rows.Add(new object[]  7, "Hi" );
            dt2.Columns.Add("a.name", typeof(string));
            dt2.Columns.Add("b.name", typeof(string));
            dt2.Rows.Add(new object[]  1, "Hi" );
            dt2.Rows.Add(new object[]  2, "Hi" );
            dt2.Rows.Add(new object[]  3, "Hi" );
            dt2.Rows.Add(new object[]  4, "Hi" );
            dt2.Rows.Add(new object[]  5, "Hi" );
            dt2.Rows.Add(new object[]  6, "Hi" );
            dt2.Rows.Add(new object[]  7, "Hi" );
            r1.DataContext = dt1;
            r2.DataContext = dt2;
        
    

我会告诉你会发生什么。顶部数据网格填充有列标题和数据。底部数据网格有列标题,但所有行都是空白的。

【问题讨论】:

您在创建该命名空间时遇到了糟糕的一天吗? 【参考方案1】:

我最终使用了 ONE DOT LEADER 的替代品,效果很好。 我从一个 XML 文件中导入了我的数据,而不是在我的代码中到处使用string.replace(".","\x2024");,而是更容易更改导入文件。

Before
<Components Description="Thru Tee" Size="0.5" Kv="0.54" />
After
<Components Description="Thru Tee" Size="0&#x2024;5" Kv="0.54" />

【讨论】:

【参考方案2】:

您可以将 AutoGenerateColumns 设置为 true 并添加一个事件处理程序来处理任何句点(或其他特殊字符):

    <DataGrid
    Name="r2"
          ItemsSource="Binding Path=."
          AutoGeneratingColumn="r2_AutoGeneratingColumn">
    </DataGrid>

代码隐藏:

private void r2_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)

    if (e.PropertyName.Contains('.') && e.Column is DataGridBoundColumn)
    
        DataGridBoundColumn dataGridBoundColumn = e.Column as DataGridBoundColumn;
        dataGridBoundColumn.Binding = new Binding("[" + e.PropertyName + "]");
    

这在 MVVM 场景中对我来说效果更好。

【讨论】:

我不得不在 wpf 中为我的数据网格使用相同的解决方案,但我正在处理的是当单元格值已更新(编辑模式)并且我按 Enter 键(提交值)时的问题,应用程序崩溃一般除外“对象引用未设置为对象的实例”,堆栈跟踪:“在 System.Windows.Data.BindingGroup.UpdateAndValidate(ValidationStep validationStep) 在 System.Windows.Data 的 System.Windows.Data.BindingGroup.UpdateValues()。 BindingGroup.CommitEdit()”。你有类似的问题吗? 对我之前的评论只有一条评论,我确实将绑定路径从“-./#”更改为“[-^.^/#]” - 这些列标题中应允许使用特殊字符。感谢您的帮助 我发现here,为了不搞砸排序还添加:dataGridBoundColumn.SortMemberPath = e.PropertyName;【参考方案3】:

绑定路径解析器错误地解释了第二个表的列名中的句号。查看此示例运行时的调试输出,您可以看到自动生成的列已绑定到“a”和“b”而不是“a.name”和“b.name”

System.Windows.Data Error: 40 : BindingExpression path error: 'a' property not found on 'object' ''DataRowView' ... etc.
System.Windows.Data Error: 40 : BindingExpression path error: 'b' property not found on 'object' ''DataRowView' ... etc.

在绑定路径中有许多具有特殊含义的不同字符,包括句号 ('.')、斜杠 ('/')、方括号 ('[',']') 和圆括号 ('( ',')'),括号会导致你的应用程序崩溃。这些特殊字符可以通过用方括号包围绑定路径来转义。有关路径和字符转义的更多信息可以在Binding Declarations Overview 中找到

要解决此问题,您必须设置 AutoGenerateColumns="False" 并在 xaml 中指定列绑定:

    <DataGrid
    x:Name="r2"
          ItemsSource="Binding ." AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridTextColumn Header="a.name" Binding="Binding Path=[a.name]" />
            <DataGridTextColumn Header="b.name" Binding="Binding Path=[b.name]" />
        </DataGrid.Columns>
    </DataGrid>

或以编程方式在后面的代码中

        r2.AutoGenerateColumns = false;
        foreach( DataColumn column in dt2.Columns )
        
            var gridColumn = new DataGridTextColumn()
            
                Header = column.ColumnName,
                Binding = new Binding( "[" + column.ColumnName + "]" )
            ;

            r2.Columns.Add( gridColumn );
        

        r2.DataContext = dt2;

【讨论】:

但是如果列名中有括号怎么办?这不会弄乱这种方法吗? (我知道这已经很老了,但我现在遇到了这个问题:))【参考方案4】:

FULL STOP(句点/点)字符不起作用。 即使用 x\002E 转义也没有用。

这是使用中点字符的折衷方案:

dt1.Columns.Add("a\x00B7name", typeof(string));  
dt1.Columns.Add("b\x00B7name", typeof(string));

【讨论】:

比 MIDDLE DOT 更好的选择可能是ONE DOT LEADER (U+2024)。 @ScottWhitlock 和 Zamboni Ahahahah,这太棒了!用一个非常简单而绝妙的想法解决了愚蠢的错误

以上是关于带点的 DataTable 列名称是啥导致它们不适合 WPF 的 DataGrid 控件?的主要内容,如果未能解决你的问题,请参考以下文章

Primefaces 动态列不适用于延迟加载

Elasticsearch:Dot expander processor - 将带点的字段 foor.bar 扩展为 Object

Elasticsearch:Dot expander processor - 将带点的字段 foor.bar 扩展为 Object

freemarker - 带点的变量名

带点的哈希表键

具有列的多个可能名称的DataTable