Ich bin neu bei WPF. Ich möchte nur wissen, wie wir einem DataGrid in WPF programmgesteuert Spalten und Zeilen hinzufügen sollen. So wie wir es früher in Windows-Formularen gemacht haben. Erstellen Sie Tabellenspalten und -zeilen und binden Sie sie an DataGrid.
Ich glaube, WPF DataGrid ist etwas anders als das, das in ASP.net und Windows Form verwendet wird (korrigieren Sie mich, wenn ich falsch liege).
Ich habe die Anzahl der Zeilen und Spalten, die ich in DataGrid zeichnen muss, damit der Benutzer die Daten in den Zellen bearbeiten kann.
Binding("[FirstName]")
meine vorherige Antwort unten , funktioniert, beim Binden großer Datenmengen jedoch erheblich langsamer ist.DataItem
ein Objekt aussehen?Versuchen Sie dies, es funktioniert zu 100%: Fügen Sie Spalten und Zeilen programmgesteuert hinzu: Sie müssen zuerst eine Elementklasse erstellen:
public class Item { public int Num { get; set; } public string Start { get; set; } public string Finich { get; set; } } private void generate_columns() { DataGridTextColumn c1 = new DataGridTextColumn(); c1.Header = "Num"; c1.Binding = new Binding("Num"); c1.Width = 110; dataGrid1.Columns.Add(c1); DataGridTextColumn c2 = new DataGridTextColumn(); c2.Header = "Start"; c2.Width = 110; c2.Binding = new Binding("Start"); dataGrid1.Columns.Add(c2); DataGridTextColumn c3 = new DataGridTextColumn(); c3.Header = "Finich"; c3.Width = 110; c3.Binding = new Binding("Finich"); dataGrid1.Columns.Add(c3); dataGrid1.Items.Add(new Item() { Num = 1, Start = "2012, 8, 15", Finich = "2012, 9, 15" }); dataGrid1.Items.Add(new Item() { Num = 2, Start = "2012, 12, 15", Finich = "2013, 2, 1" }); dataGrid1.Items.Add(new Item() { Num = 3, Start = "2012, 8, 1", Finich = "2012, 11, 15" }); }
quelle
Ich hatte das gleiche Problem. Das Hinzufügen neuer Zeilen zu WPF
DataGrid
erfordert einen Trick.DataGrid
stützt sich auf Eigenschaftsfelder eines Objektobjekts.ExpandoObject
ermöglicht das dynamische Hinzufügen neuer Eigenschaften. Der folgende Code erklärt, wie es geht:// using System.Dynamic; DataGrid dataGrid; string[] labels = new string[] { "Column 0", "Column 1", "Column 2" }; foreach (string label in labels) { DataGridTextColumn column = new DataGridTextColumn(); column.Header = label; column.Binding = new Binding(label.Replace(' ', '_')); dataGrid.Columns.Add(column); } int[] values = new int[] { 0, 1, 2 }; dynamic row = new ExpandoObject(); for (int i = 0; i < labels.Length; i++) ((IDictionary<String, Object>)row)[labels[i].Replace(' ', '_')] = values[i]; dataGrid.Items.Add(row);
//bearbeiten:
Beachten Sie, dass dies nicht die Art und Weise ist, wie die Komponente verwendet werden soll. Dies vereinfacht jedoch erheblich, wenn Sie nur programmgesteuert Daten generiert haben (z. B. in meinem Fall: eine Folge von Funktionen und die Ausgabe eines neuronalen Netzwerks).
quelle
Ich habe eine Lösung gefunden, die zur Laufzeit Spalten hinzufügt und an a bindet
DataTable
.Leider sind 47 Spalten, die auf diese Weise definiert wurden, für mich nicht schnell genug an die Daten gebunden. Irgendwelche Vorschläge?
xaml
<DataGrid Name="dataGrid" AutoGenerateColumns="False" ItemsSource="{Binding}"> </DataGrid>
xaml.cs using System.Windows.Data;
if (table != null) // table is a DataTable { foreach (DataColumn col in table.Columns) { dataGrid.Columns.Add( new DataGridTextColumn { Header = col.ColumnName, Binding = new Binding(string.Format("[{0}]", col.ColumnName)) }); } dataGrid.DataContext = table; }
quelle
edit : sorry, ich habe den unten genannten code nicht mehr. Es war eine saubere Lösung, obwohl komplex.
Ich habe ein Beispielprojekt veröffentlicht, in dem beschrieben wird, wie PropertyDescriptor- und Lambda-Delegaten mit dynamischer ObservableCollection und DynamicObject verwendet werden, um ein Raster mit stark typisierten Spaltendefinitionen zu füllen .
Spalten können zur Laufzeit dynamisch hinzugefügt / entfernt werden . Wenn Ihre Daten kein Objekt mit bekanntem Typ sind, können Sie eine Datenstruktur erstellen, die den Zugriff für eine beliebige Anzahl von Spalten ermöglicht, und für jede "Spalte" einen PropertyDescriptor angeben.
Zum Beispiel:
IList<string> ColumnNames { get; set; } //dict.key is column name, dict.value is value Dictionary<string, string> Rows { get; set; }
Sie können Spalten folgendermaßen definieren:
var descriptors= new List<PropertyDescriptor>(); //retrieve column name from preprepared list or retrieve from one of the items in dictionary foreach(var columnName in ColumnNames) descriptors.Add(new DynamicPropertyDescriptor<Dictionary, string>(ColumnName, x => x[columnName])) MyItemsCollection = new DynamicDataGridSource(Rows, descriptors)
Oder noch besser bei einigen realen Objekten
public class User { public string FirstName { get; set; } public string LastName{ get; set; } ... }
Sie können stark typisierte Spalten angeben (bezogen auf Ihr Datenmodell):
var propertyDescriptors = new List<PropertyDescriptor> { new DynamicPropertyDescriptor<User, string>("First name", x => x.FirstName ), new DynamicPropertyDescriptor<User, string>("Last name", x => x.LastName ), ... } var users = retrieve some users Users = new DynamicDataGridSource<User>(users, propertyDescriptors, PropertyChangedListeningMode.Handler);
Dann binden Sie einfach an Benutzer Sammlungen und Spalten werden automatisch generiert, wenn Sie sie spezifizieren. An Eigenschaftsbeschreibungen übergebene Zeichenfolgen sind Namen für Spaltenüberschriften. Zur Laufzeit können Sie den 'Benutzern' weitere PropertyDescriptors hinzufügen und dem Raster eine weitere Spalte hinzufügen.
quelle
Wenn Sie die Datenbindung bereits eingerichtet haben, ist die Antwort von John Myczek vollständig.
Wenn nicht, haben Sie mindestens zwei mir bekannte Optionen, wenn Sie die Quelle Ihrer Daten angeben möchten. (Ich bin mir jedoch nicht sicher, ob dies den meisten Richtlinien wie MVVM entspricht oder nicht.)
Option 1: wie JohnB sagte. Aber ich denke, Sie sollten Ihre eigene definierte Sammlung anstelle einer schwach typisierten DataTable verwenden (keine Beleidigung, aber Sie können anhand des Codes nicht erkennen, was jede Spalte darstellt).
xaml.cs
DataContext = myCollection; //myCollection is a `ICollection<YourType>` preferably `ObservableCollection<YourType> - option 2) Declare the name of the Datagrid in xaml <WpfToolkit:DataGrid Name=dataGrid}>
in xaml.cs
Wenn für Ihren Typ eine Eigenschaft FirstName definiert ist, können Sie das tun, worauf John Myczek hingewiesen hat.
DataGridTextColumn textColumn = new DataGridTextColumn(); dataColumn.Header = "First Name"; dataColumn.Binding = new Binding("FirstName"); dataGrid.Columns.Add(textColumn);
Dies funktioniert offensichtlich nicht, wenn Sie keine Eigenschaften kennen, die Sie in Ihrem dataGrid anzeigen müssen, aber wenn dies der Fall ist, werden Sie mehr Probleme haben, und ich glaube, dass dies hier nicht möglich ist.
quelle
So binden Sie die DataTable in die DataGridTextColumn in CodeBehind xaml
<DataGrid Name="TrkDataGrid" AutoGenerateColumns="False" ItemsSource="{Binding}"> </DataGrid>
xaml.cs
foreach (DataColumn col in dt.Columns) { TrkDataGrid.Columns.Add( new DataGridTextColumn { Header = col.ColumnName, Binding = new Binding(string.Format("[{0}]", col.ColumnName)) }); } TrkDataGrid.ItemsSource= dt.DefaultView;
quelle
Wenn Sie die Datenbindung bereits eingerichtet haben, ist die Antwort von John Myczek vollständig. Wenn nicht, haben Sie mindestens zwei mir bekannte Optionen, wenn Sie die Quelle Ihrer Daten angeben möchten. (Ich bin mir jedoch nicht sicher, ob dies den meisten Richtlinien wie MVVM entspricht oder nicht.)
Dann binden Sie einfach an Benutzer Sammlungen und Spalten werden automatisch generiert, wenn Sie sie spezifizieren. An Eigenschaftsbeschreibungen übergebene Zeichenfolgen sind Namen für Spaltenüberschriften. Zur Laufzeit können Sie den 'Benutzern' weitere PropertyDescriptors hinzufügen und dem Raster eine weitere Spalte hinzufügen.
quelle