Программно добавлять столбцы и строки в WPF Datagrid
Я новичок в WPF. Я просто хочу знать, как мы должны добавлять столбцы и строки программно в DataGrid в WPF. То, как мы это делали в окнах. создавать столбцы и строки таблицы и привязывать их к DataGrid.
Я считаю, что WPF DataGrid немного отличается от используемого в ASP.net и Windows-форме (исправьте меня, если я ошибаюсь).
У меня есть количество строк и столбцов, которые мне нужно сделать в DataGrid, чтобы пользователь мог редактировать данные в ячейках.
Ответы
Ответ 1
Чтобы программно добавить строку:
DataGrid.Items.Add(new DataItem());
Чтобы программно добавить столбец:
DataGridTextColumn textColumn = new DataGridTextColumn();
textColumn.Header = "First Name";
textColumn.Binding = new Binding("FirstName");
dataGrid.Columns.Add(textColumn);
Обратитесь этот пост на доске объявлений WPF DataGrid для получения дополнительной информации.
Ответ 2
попробуйте это, он работает на 100%: добавьте столбцы и строки программно:
вам необходимо сначала создать класс элемента:
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" });
}
Ответ 3
У меня была та же проблема. Добавление новых строк в WPF DataGrid
требует трюка. DataGrid
полагается на поля свойств объекта item. ExpandoObject
позволяет динамически добавлять новые свойства. В приведенном ниже коде объясняется, как это сделать:
// 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);
//редактирование:
Обратите внимание: это не так, как этот компонент должен использоваться, однако он упрощает работу, если у вас есть только программно сгенерированные данные (например, в моем случае: последовательность функций и выход нейронной сети).
Ответ 4
Я нашел решение, которое добавляет столбцы во время выполнения и связывается с DataTable
.
К сожалению, с 47 столбцами, определенными таким образом, он не привязывается к данным, достаточно быстрому для меня. Любые предложения?
XAML
<DataGrid
Name="dataGrid"
AutoGenerateColumns="False"
ItemsSource="{Binding}">
</DataGrid>
xaml.cs используя 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;
}
Ответ 5
edit: извините, у меня больше нет кода, упомянутого ниже. Это было аккуратное решение, хотя и сложное.
Я разместил образец проекта, описывающий использование делегатов PropertyDescriptor и лямбда с динамическим ObservableCollection и DynamicObject для заполнения сетки с помощью определений столбцов строго типизированных.
Столбцы могут быть добавлены/удалены во время выполнения динамически. Если ваши данные не являются объектом с известным типом, вы можете создать структуру данных, которая разрешала бы доступ к любому количеству столбцов и указывала бы PropertyDescriptor для каждого "столбца".
Например:
IList<string> ColumnNames { get; set; }
//dict.key is column name, dict.value is value
Dictionary<string, string> Rows { get; set; }
Вы можете определить столбцы следующим образом:
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)
Или даже лучше, в случае некоторых реальных объектов
public class User
{
public string FirstName { get; set; }
public string LastName{ get; set; }
...
}
Вы можете указать строго типизированные столбцы (связанные с вашей моделью данных):
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);
Затем вы просто привязываетесь к коллекциям пользователей, а столбцы автоматически генерируются, когда вы их определяете. Строки, переданные дескрипторам свойств, являются именами заголовков столбцов. Во время выполнения вы можете добавить больше PropertyDescriptors, чтобы "Пользователи" добавили еще один столбец в сетку.
Ответ 6
Если у вас уже есть привязка данных на месте, ответ Джон Мойчек отвечает.
Если нет, у вас есть как минимум 2 варианта, о которых я знаю, если вы хотите указать источник своих данных. (Однако я не уверен, действительно ли это
line с большинством рекомендаций, например MVVM)
вариант 1:, как сказал ДжонБ. Но я думаю, вы должны использовать свою собственную определенную коллекцию
вместо слабо напечатанного DataTable (без обид, но вы не можете сказать из
код, который представляет каждый столбец)
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}>
в xaml.cs
CollectionView myCollectionView =
(CollectionView)CollectionViewSource.GetDefaultView(yourCollection);
dataGrid.ItemsSource = myCollectionView;
Если ваш тип имеет свойство FirstName, вы можете сделать то, что указал Джон Мичек.
DataGridTextColumn textColumn = new DataGridTextColumn();
dataColumn.Header = "First Name";
dataColumn.Binding = new Binding("FirstName");
dataGrid.Columns.Add(textColumn);
Это явно не работает, если вы не знаете свойств, которые вам нужно будет показывать в вашем dataGrid, но если это так, у вас будет больше проблем с этим, и я считаю, что вне сферы действия здесь.
Ответ 7
Если у вас уже есть привязка данных на месте, ответ Джон Мойчек отвечает.
Если нет, у вас есть как минимум 2 варианта, о которых я знаю, если вы хотите указать источник своих данных. (Однако я не уверен, соответствует ли это большинству рекомендаций, например MVVM)
Затем вы просто привязываетесь к коллекциям пользователей, а столбцы автоматически генерируются, когда вы их определяете. Строки, переданные дескрипторам свойств, являются именами заголовков столбцов. Во время выполнения вы можете добавить больше PropertyDescriptors, чтобы "Пользователи" добавили еще один столбец в сетку.