2010-05-30 9 views
11

Ejecutar este, y confundirse:¿Qué tiene que ver con los nombres de columna DataTable con puntos que los hace inadecuados para el control DataGrid de WPF?

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

te diré lo que sucede. La cuadrícula de datos superior se rellena con encabezados de columna y datos. La cuadrícula de datos inferior tiene encabezados de columna pero todas las filas están en blanco.

+4

¿Estaba teniendo un mal día cuando creó ese espacio de nombres? – slugster

Respuesta

15

El carácter punto y en los nombres de columna de la segunda tabla se interpretan incorrectamente por el analizador ruta de enlace. Mira el resultado de la depuración, mientras que este ejemplo se está ejecutando y se puede ver que las columnas generadas automáticamente se han unido a 'a' y 'b' en lugar de 'a.name' y '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. 

Hay un número de caracteres diferentes que tienen un significado especial en una ruta de enlace que incluye punto final ('.'), Barra inclinada ('/'), corchetes ('[', ']') y paréntesis ('(', ')'), el paréntesis hará que su aplicación se cuelgue. Estos caracteres especiales se pueden escapar rodeando la ruta de enlace con corchetes. Más información acerca de las rutas y escapar personaje puede ser encontrado en el Binding Declarations Overview

Para solucionar este problema, tendrá que establecer AutoGenerateColumns = "falso" y especificar los enlaces de la columna en el 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> 

o mediante programación en el código detrás

 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; 
+0

Pero, ¿qué pasa si hay un corchete en el nombre de la columna? ¿Eso no estropeará este enfoque?(Soy consciente de que esto es muy antiguo pero tengo este problema en este momento :)) – anakic

3

El carácter FULL STOP (punto/punto) no funciona.
Incluso escapando con x \ 002E no funcionó.

Aquí es un compromiso con el carácter MEDIO PUNTO:

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

Una mejor alternativa que MIDDLE DOT podría ser [ONE DOT LEADER (U + 2024)] (http://www.fileformat.info/info/unicode/char/2024/index.htm). –

+0

@ScottWhitlock y Zamboni Ahahahah, ¡esto es genial! Errores estúpidos resueltos con una idea realmente simple y brillante –

17

puede mantener AutoGenerateColumns establecidas en true y añadir un manejador de sucesos para hacer frente a cualquier período (u otros caracteres especiales):

<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 + "]"); 
    } 
} 

Esto funcionó mejor para mí en un escenario MVVM.

+0

Tuve que usar la misma solución para mi cuadrícula de datos en wpf, pero lo que estoy tratando es el problema cuando Cell Valllue se ha actualizado (modo de edición) y presiono Enter (confirmar valor), la aplicación se bloquea con general exc. "Referencia de objeto no establecida en una instancia de un objeto", stack trace: "en System.Windows.Data.BindingGroup.UpdateValues ​​() en System.Windows.Data.BindingGroup.UpdateAndValidate (ValidationStep validationStep) en System.Windows. Data.BindingGroup.CommitEdit() ". ¿Has tenido un problema similar? – stenly

+0

y solo un comentario a mi anterior, cambié la ruta de enlace de "_-./#" a "[_- ^. ^/#]" - estos caracteres especiales deberían estar permitidos en el encabezado de la columna. Gracias por la ayuda – stenly

+1

Como encontré [aquí] (http://stackoverflow.com/questions/8010614/datagrid-header-sort-error-bound-to-dataview), para no estropear la ordenación también agregue: dataGridBoundColumn.SortMemberPath = e.PropertyName; – anakic

0

Terminé usando el sustituto de ONE DOT LEADER y funcionó muy bien. Importé mis datos de un archivo XML y, en lugar de usar string.replace(".","\x2024"); en todas partes de mi código, fue más fácil cambiar el archivo de importación.

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