2010-05-30 6 views
11

Run questo, e essere confuso:Che cosa si tratta dei nomi delle colonne DataTable con punti che li rendono inadatti al controllo DataGrid di 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; 
     } 
    } 
} 

ti dirò cosa succede. Il datagrid superiore viene popolato con intestazioni di colonna e dati. Il datagrid inferiore ha intestazioni di colonna ma tutte le righe sono vuote.

+4

Stavi avendo una brutta giornata quando hai creato quel namespace? – slugster

risposta

15

Il carattere punto nei nomi di colonna della seconda tabella sono erroneamente interpretato dal parser percorso vincolante. Guardate l'output di debug, mentre questo esempio è in esecuzione e si può vedere che le colonne generate automaticamente sono stati tenuti a 'a' e 'b', piuttosto che 'a.name' e '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. 

Ci sono un certo numero di caratteri diversi che hanno un significato speciale in un percorso di bind incluso stop completo ('.'), Barra ('/'), parentesi quadre ('[', ']') e parentesi ('(', ')'), la parentesi causerà l'arresto anomalo dell'app. Questi caratteri speciali possono essere sfuggiti circondando il percorso di rilegatura con parentesi quadre. Maggiori informazioni sui percorsi e fuggire carattere può essere trovato nel Binding Declarations Overview

Per risolvere questo problema si dovrà impostare AutoGenerateColumns = "false" e specificare i vincoli di colonna nella 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> 

oa livello di programmazione in codice dietro

 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

Ma cosa succede se c'è una parentesi nel nome della colonna? Non rovinerà questo approccio?(Sono consapevole che questo è molto vecchio ma ho questo problema in questo momento :)) – anakic

3

Il carattere FULL STOP (punto/punto) non funziona.
Anche l'escape con x \ 002E non ha funzionato.

Qui è un compromesso usando il carattere MEDIO DOT:

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

Un'alternativa migliore di MIDDLE DOT potrebbe essere [ONE DOT LEADER (U + 2024)] (http://www.fileformat.info/info/unicode/char/2024/index.htm). –

+0

@ScottWhitlock e Zamboni Ahahahah, questo è FANTASTICO! Bug stupidi risolti con un'idea davvero semplice e brillante –

17

È possibile mantenere AutoGenerateColumns impostata su true e aggiungere un EventHandler per affrontare eventuali periodi (o altri caratteri speciali):

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

Questo ha funzionato meglio per me in uno scenario MVVM.

+0

Ho dovuto usare la stessa soluzione per il mio datagrid in wpf, ma quello che sto trattando è il problema quando è stato aggiornato cell vallue (modalità di modifica) e premo Invio (valore commit), l'app si arresta in modo anomalo con l'esc generale. "Oggetto non impostato a un'istanza di un oggetto", dello stack: "a System.Windows.Data.BindingGroup.UpdateValues ​​() a System.Windows.Data.BindingGroup.UpdateAndValidate (ValidationStep validationStep) a System.Windows. Data.BindingGroup.CommitEdit()". Hai avuto un problema simile? – stenly

+0

e un solo commento al mio precedente, ho cambiato il percorso di collegamento da "_-./#" a "[_- ^. ^/#]" - questi caratteri speciali dovrebbero essere consentiti nell'intestazione della colonna. Grazie per l'aiuto – stenly

+1

Come ho trovato [qui] (http://stackoverflow.com/questions/8010614/datagrid-header-sort-error-bound-to-dataview), per non rovinare l'ordinamento aggiungere anche: dataGridBoundColumn.SortMemberPath = e.PropertyName; – anakic

0

Ho finito per utilizzare il ONE DOT LEADER e ha funzionato benissimo. Ho importato i miei dati da un file XML e invece di usare string.replace(".","\x2024"); ovunque nel mio codice è stato più semplice cambiare il file di importazione.

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