代码之家  ›  专栏  ›  技术社区  ›  Tom Ritter

对于带有点的DataTable列名,有什么不适合于WPF的DataGrid控件?

  •  13
  • Tom Ritter  · 技术社区  · 15 年前

    运行此命令,并将其混淆:

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

    Codebehind:

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

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

    4 回复  |  直到 8 年前
        1
  •  16
  •   bstoney    14 年前

    绑定路径分析器错误地解释了第二个表的列名中的完整停止字符。在本例运行时查看调试输出,可以看到自动生成的列已绑定到“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;
    
        2
  •  17
  •   TRX    12 年前

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

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

    Codebehind:

    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场景中,这对我更有效。

        3
  •  3
  •   Zamboni    15 年前

    完全停止(句点/点)字符不起作用。
    即使使用x\002e进行转义也不起作用。

    以下是使用中间点字符的折衷方案:

    dt1.Columns.Add("a\x00B7name", typeof(string));  
    dt1.Columns.Add("b\x00B7name", typeof(string));
    
        4
  •  1
  •   Icy    8 年前

    最后我用了一点引线代替了它,效果很好。 我从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" />