2011-01-15 8 views
7

Una domanda relativamente semplice. Ho un datagridview, che tutto ciò che fa è visualizzare le statistiche. Non c'è modifica/aggiunta/eliminazione di righe. La vista datagrid è associata a un elenco. Tutto quello che voglio ottenere è avere l'utente in grado di ordinare le colonne.Ordinamento dell'origine dati Datagridview nell'elenco <T> dove T è anonimo

Come previsto, le colonne non sono ordinabili, ma le informazioni visualizzate sono quelle desiderate. La mia domanda è come rendere l'ordinamento DataGridView basato sul tipo di colonna con la quantità meno complicata e minima di codice, in quanto il codice verrà utilizzato più volte in tutto.

Questa applicazione utilizzava un DataBase con viste. Queste viste popolavano quindi DataGridViews. Le viste sono ancora intorno, quindi una possibile soluzione potrebbe essere:

DataBase.ViewMarketValue temp = new DataBase.ViewMarketValue() 

_markets.ForEach(market => temp.AddViewMarketValueRow(_cities[market.Location].Name, market.Value); 
dataGridView1.DataSource = temp; 

Ciò comporta la desiderata: un datagridview che ha tutte le informazioni ed è sortable. L'unico problema è che sembra sbagliato usare le viste in questo aspetto. Quindi cosa dovrei fare?

risposta

10

Per poter ordinare automaticamente i dati nello DataGridView, è necessario un insieme che implementa IBindingListView. Nel BCL, le uniche classi che implementano questa interfaccia sono DataView e BindingSource (ma quest'ultimo supporta solo l'ordinamento se anche l'origine dati sottostante lo supporta).

Quindi, sono disponibili diverse opzioni:

  • creare un DataTable per contenere i dati, e associarlo al DataGridView (sarà effettivamente legarsi al DefaultView del DataTable)
  • creare la propria collezione classe che implementa IBindingListView
  • utilizza un'implementazione esistente, come la classe AdvancedList<T> pubblicata da Marc Gravell in this post. Sarà inoltre necessario aggiungere un costruttore per creare l'elenco dal risultato della query:

    public AdvancedList(IEnumerable<T> collection) 
    { 
        foreach (var item in collection) 
        { 
         Add(item); 
        } 
    } 
    

Poiché il risultato della query è un tipo anonimo, non sarà in grado di chiamare il costruttore direttamente. Il modo più semplice per risolvere il problema è sfruttare l'inferenza di tipo, creando un metodo generico che creerà l'elenco. Per comodità, è possibile crearlo come un metodo di estensione:

public static AdvancedList<T> ToAdvancedList<T>(this IEnumerable<T> source) 
{ 
    return new AdvancedList<T>(source); 
} 

è quindi possibile utilizzare in quel modo:

dataGridView1.DataSource = _markets.Select(market => 
    new { _cities[market.Location].Name, market.Value}).ToAdvancedList(); 
+0

soluzione molto buona! La mia unica lamentela (ed è piccola) è che l'ordinamento non è veloce come l'ideale, ma è tollerabile e la cosa migliore finora. –

+1

È lento perché utilizza la riflessione per ottenere il valore della proprietà. È possibile modificare facilmente la classe PropertyComparer in modo che generi un delegato al momento della creazione e utilizzi questo delegato anziché property.GetValue –

+0

@ThomasLevesque sarebbe fantastico se fosse possibile inserire alcuni snippet di codice per implementare il suggerimento. Grazie – Esen

Problemi correlati