Wie binde ich eine List <string> an ein DataGridView-Steuerelement?

84

Ich habe eine einfache List<string>und möchte, dass sie in einer DataGridViewSpalte angezeigt wird.
Wenn die Liste komplexere Objekte enthalten würde, würde die Liste einfach als Wert ihrer DataSourceEigenschaft festgelegt.

Aber wenn Sie dies tun:

myDataGridView.DataSource = myStringList;

Ich erhalte eine Spalte mit dem Namen Lengthund die Längen der Zeichenfolgen werden angezeigt.

Wie werden die tatsächlichen Zeichenfolgenwerte aus der Liste in einer Spalte angezeigt?

Agnieszka
quelle

Antworten:

70

Dies liegt daran, dass DataGridView nach Eigenschaften für enthaltende Objekte sucht. Für Zeichenfolgen gibt es nur eine Eigenschaft - Länge. Sie benötigen also einen Wrapper für eine solche Zeichenfolge

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

Binden Sie dann das List<StringValue>Objekt an Ihr Raster. Es klappt

sinm
quelle
3
Die DataPropertyNameder Spalte muss seinValue
Rémi
Was ist mit Gruppierung? Jetzt ist "A" nicht gleich "A" und ich habe zwei Gruppen "A".
Rover
97

Versuche dies:

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

Ich hoffe das hilft.

Tamanna Jain
quelle
13
Wenn Sie eine Liste anstelle von IList verwenden, können Sie diese verwenden List.ConvertAll(x => new { Value = x});.
Scotty.NET
7
Dies funktioniert, aber Änderungen an list_string aktualisieren die DataGridView nicht.
Pedro77
Um das Grid zu aktualisieren, muss die linq-Anweisung erneut ausgeführt werden.
Jeff
1
Was ist dgvSelectedNode.Show ()?
Duan Walker
18

Das Folgende sollte funktionieren, solange Sie an etwas gebunden sind, das IEnumerable <string> implementiert. Die Spalte wird direkt an die Zeichenfolge selbst und nicht an einen Eigenschaftspfad dieses Zeichenfolgenobjekts gebunden.

<sdk:DataGridTextColumn Binding="{Binding}" />
jamisonLikeCode
quelle
Ich habe diesen Vorschlag getestet und er hat richtig funktioniert. Es ist sauberer als die anderen Lösungen.
Gustavo Cardoso
7
Ist das nicht spezifisch für Silverlight?
NoviceProgrammer
2
Dies funktioniert auch in WPF. Warum sollten Sie einen falschen Kommentar positiv bewerten?
Boppity Bop
4
Downvoting, da die ursprüngliche Frage das Tag "datagridview" hat, das die Kontrolle über Winforms darstellt. Diese Lösung gilt nicht für Winfroms.
VIS
13

Sie können auch linq- und anonyme Typen verwenden, um das gleiche Ergebnis mit viel weniger Code wie hier beschrieben zu erzielen .

UPDATE: Blog ist ausgefallen, hier ist der Inhalt:

(..) Die in der Tabelle angezeigten Werte stellen die Länge von Zeichenfolgen anstelle von Zeichenfolgenwerten dar (!). Es mag seltsam erscheinen, aber so funktioniert der Bindungsmechanismus standardmäßig - bei einem Objekt wird versucht, an die erste Eigenschaft davon zu binden Objekt (die erste Eigenschaft, die es finden kann). Wenn eine Instanz übergeben wird, ist die String-Klasse, an die sie gebunden wird, String.Length, da es keine andere Eigenschaft gibt, die den eigentlichen String selbst bereitstellen würde.

Das heißt, um unsere Bindung richtig zu machen, benötigen wir ein Wrapper-Objekt, das den tatsächlichen Wert eines Strings als Eigenschaft verfügbar macht:

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

Diese Lösung funktioniert zwar wie erwartet, erfordert jedoch einige Codezeilen (hauptsächlich, um die Liste der Zeichenfolgen in die Liste der Zeichenfolgen-Wrapper zu konvertieren).

Wir können diese Lösung verbessern, indem wir LINQ und anonyme Typen verwenden. Wir verwenden die LINQ-Abfrage, um eine neue Liste von String-Wrappern zu erstellen (String-Wrapper ist in unserem Fall ein anonymer Typ).

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

 Table1.SetDataBinding(values.ToList());

Die letzte Änderung, die wir vornehmen werden, besteht darin, den LINQ-Code in eine Erweiterungsmethode zu verschieben:

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

Auf diese Weise können wir den Code wiederverwenden, indem wir eine einzelne Methode für eine beliebige Sammlung von Zeichenfolgen aufrufen:

Table1.SetDataBinding(testData.CreateStringWrapperForBinding());
Jarek Kardas
quelle
8

Dies ist ein häufiges Problem. Eine andere Möglichkeit ist die Verwendung des DataTable-Objekts

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

Dieses Problem wird hier ausführlich beschrieben: http://www.psworld.pl/Programming/BindingListOfString

user1246920
quelle
2
Die Datentabelle ist jedoch schwerer als List <T>, und die meisten Entwickler würden die Verwendung der Datentabelle vermeiden.
Musikero31
2

Beim Zuweisen sehr großer Listen über LINQ können Leistungsprobleme auftreten. Die folgende Lösung eignet sich für große Listen und ohne Unterklasse String:

Setzen Sie DataGridView (hier "View") in den virtuellen Modus, erstellen Sie die gewünschte Spalte und überschreiben / registrieren Sie sich für das Ereignis 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();
}

Dann können Sie Ihre Liste einfach DataGridView zuweisen:

List<String> MyList = ...
View.DataSource = MyList;
user3042599
quelle
2

Versuche dies :

//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);
}
Neojt
quelle
1
Sie erkennen, dass diese Frage wie 6 Jahre alt ist und richtig beantwortet wurde?
Hozikimaru
2
Sie müssen zuerst Spalten zur Datagrid-Ansicht hinzufügen, sonst funktioniert dies nicht
Deltanin
0

Eine Alternative besteht darin, eine neue Hilfsfunktion zu verwenden, die Werte aus List übernimmt und in der DataGridView wie folgt aktualisiert:

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

Dann können wir diese Funktion folgendermaßen aufrufen:

    DisplayStringListInDataGrid(<nameOfListWithStrings>, ref <nameOfDataGridViewToDisplay>, <nameToBeGivenForTheNewColumn>);
Sudeep
quelle