Come associare un List <string> a un controllo DataGridView?


85

Ho un semplice List<string>e vorrei che fosse visualizzato in una DataGridViewcolonna.
Se l'elenco contenesse oggetti più complessi, stabilirebbe semplicemente l'elenco come valore della sua DataSourceproprietà.

Ma quando lo fai:

myDataGridView.DataSource = myStringList;

Ottengo una colonna chiamata Lengthe vengono visualizzate le lunghezze delle stringhe.

Come visualizzare i valori di stringa effettivi dall'elenco in una colonna?

Risposte:


70

Questo perché DataGridView cerca le proprietà di contenere oggetti. Per la stringa c'è solo una proprietà - length. Quindi, hai bisogno di un wrapper per una stringa come questa

public class StringValue
{
    public StringValue(string s)
    {
        _value = s;
    }
    public string Value { get { return _value; } set { _value = value; } }
    string _value;
}

Quindi associa l' List<StringValue>oggetto alla griglia. Funziona


3
La DataPropertyNamecolonna deve essereValue
Rémi

E il raggruppamento? Ora "A" non è uguale ad "A" e ho due gruppi "A".
Rover

98

Prova questo:

IList<String> list_string= new List<String>();
DataGridView.DataSource = list_string.Select(x => new { Value = x }).ToList();
dgvSelectedNode.Show();

Spero che possa aiutare.


13
Se stai usando un List invece di IList puoi usare List.ConvertAll(x => new { Value = x});.
Scotty.NET

7
Funziona ma le modifiche a list_string non aggiorneranno DataGridView.
Pedro77

Per aggiornare la griglia è necessario eseguire nuovamente l'istruzione linq.
Jeff

1
cos'è dgvSelectedNode.Show ()?
Duan Walker

18

Quanto segue dovrebbe funzionare fintanto che sei vincolato a tutto ciò che implementa IEnumerable <string>. Assocerà la colonna direttamente alla stringa stessa, piuttosto che a un percorso di proprietà di quell'oggetto stringa.

<sdk:DataGridTextColumn Binding="{Binding}" />

Ho testato questo suggerimento e ha funzionato bene. È più pulito delle altre soluzioni.
Gustavo Cardoso

7
Non è specifico per Silverlight?
NoviceProgrammer

2
funziona anche in WPF .. perché voteresti un commento errato?
Boppity Bop

4
Downvoting perché la domanda originale ha il tag "datagridview", che è il controllo di winforms. Questa soluzione non si applica a winfrom.
VIS

13

puoi anche usare linq e tipi anonimi per ottenere lo stesso risultato con molto meno codice come descritto qui .

AGGIORNAMENTO: il blog non funziona, ecco il contenuto:

(..) I valori mostrati nella tabella rappresentano la lunghezza delle stringhe invece dei valori delle stringhe (!) Può sembrare strano, ma è così che funziona il meccanismo di associazione di default - dato un oggetto proverà a legarsi alla prima proprietà di quello oggetto (la prima proprietà che può trovare). Quando viene passata un'istanza, la classe String la proprietà a cui si associa è String.Length poiché non esistono altre proprietà che fornirebbero la stringa effettiva stessa.

Ciò significa che per ottenere il diritto di associazione, abbiamo bisogno di un oggetto wrapper che esponga il valore effettivo di una stringa come proprietà:

public class StringWrapper
    {
     string stringValue;
     public string StringValue { get { return stringValue; } set { stringValue = value; } }

     public StringWrapper(string s)
     {
     StringValue = s;
     }
  }   

   List<StringWrapper> testData = new List<StringWrapper>();

   // add data to the list / convert list of strings to list of string wrappers

  Table1.SetDataBinding(testdata);

Sebbene questa soluzione funzioni come previsto, richiede alcune righe di codice (principalmente per convertire un elenco di stringhe nell'elenco di wrapper di stringhe).

Possiamo migliorare questa soluzione utilizzando LINQ e tipi anonimi: utilizzeremo la query LINQ per creare un nuovo elenco di wrapper di stringhe (nel nostro caso il wrapper di stringhe sarà un tipo anonimo).

 var values = from data in testData select new { Value = data };

 Table1.SetDataBinding(values.ToList());

L'ultima modifica che apporteremo è spostare il codice LINQ in un metodo di estensione:

public static class StringExtensions
  {
     public static IEnumerable CreateStringWrapperForBinding(this IEnumerable<string> strings)
     {
     var values = from data in strings
     select new { Value = data };

     return values.ToList();
     }

In questo modo possiamo riutilizzare il codice chiamando il metodo singolo su qualsiasi raccolta di stringhe:

Table1.SetDataBinding(testData.CreateStringWrapperForBinding());

8

Questo è un problema comune, un altro modo è utilizzare l'oggetto DataTable

DataTable dt = new DataTable();
dt.Columns.Add("column name");

dt.Rows.Add(new object[] { "Item 1" });
dt.Rows.Add(new object[] { "Item 2" });
dt.Rows.Add(new object[] { "Item 3" });

Questo problema è descritto in dettaglio qui: http://www.psworld.pl/Programming/BindingListOfString


2
Ma datatable è più pesante di List <T> e la maggior parte degli sviluppatori eviterebbe l'uso di datatable.
Musikero31

2

Potresti incorrere in problemi di prestazioni durante l'assegnazione di elenchi molto grandi tramite LINQ. La seguente soluzione è adatta per elenchi di grandi dimensioni e senza sottoclasse String:

Imposta DataGridView (qui "Visualizza") in modalità virtuale, crea la colonna che ti serve e sostituisci / registrati per l'evento CellValueNeeded

private void View_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
{
    // Optionally: check for column index if you got more columns
    e.Value = View.Rows[e.RowIndex].DataBoundItem.ToString();
}

quindi puoi semplicemente assegnare il tuo elenco a DataGridView:

List<String> MyList = ...
View.DataSource = MyList;

2

Prova questo :

//i have a 
List<string> g_list = new List<string>();

//i put manually the values... (for this example)
g_list.Add("aaa");
g_list.Add("bbb");
g_list.Add("ccc");

//for each string add a row in dataGridView and put the l_str value...
foreach (string l_str in g_list)
{
    dataGridView1.Rows.Add(l_str);
}

1
Ti rendi conto che questa domanda ha 6 anni e hai avuto risposta, giusto?
Hozikimaru

2
devi prima aggiungere colonne alla vista datagrid o questo non funzionerà
deltanine

0

Un'alternativa consiste nell'usare una nuova funzione di supporto che prenderà i valori da List e si aggiornerà in DataGridView come segue:

    private void DisplayStringListInDataGrid(List<string> passedList, ref DataGridView gridToUpdate, string newColumnHeader)
    {
        DataTable gridData = new DataTable();
        gridData.Columns.Add(newColumnHeader);

        foreach (string listItem in passedList)
        {
            gridData.Rows.Add(listItem);
        }

        BindingSource gridDataBinder = new BindingSource();
        gridDataBinder.DataSource = gridData;
        dgDataBeingProcessed.DataSource = gridDataBinder;
    }

Quindi possiamo chiamare questa funzione nel modo seguente:

    DisplayStringListInDataGrid(<nameOfListWithStrings>, ref <nameOfDataGridViewToDisplay>, <nameToBeGivenForTheNewColumn>);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.