2009-04-01 13 views
62

Я новичок в WPF. Я просто хочу знать, как мы должны добавлять столбцы и строки программно в DataGrid в WPF. То, как мы это делали в окнах. создавать столбцы и строки таблицы и привязывать их к DataGrid.программно добавить столбец и строки в WPF Datagrid

Я считаю, что WPF DataGrid немного отличается от используемого в ASP.net и Windows форме (исправьте меня, если я ошибаюсь).

У меня есть количество строк и столбцов, которые мне нужно сделать в DataGrid, чтобы пользователь мог редактировать данные в ячейках.

ответ

65

Чтобы программно добавить строку:

DataGrid.Items.Add(new DataItem()); 

Чтобы программно добавить столбец:

DataGridTextColumn textColumn = new DataGridTextColumn(); 
textColumn.Header = "First Name"; 
textColumn.Binding = new Binding("FirstName"); 
dataGrid.Columns.Add(textColumn); 

Отъезд this post на доске обсуждений WPF DataGrid для получения дополнительной информации.

+4

-1: потому что вы показываете мучительно легкую часть, но не так, как на самом деле привязать данные к этим во время выполнения добавлены столбцы. Я уверен, что Энди хочет создать приложение, которое отображает какие-то данные, а не только имена столбцов. – JohnB

+0

Речь идет только о настройке свойств в DataGridTextColumn. Я обновил ответ. –

+0

+1: Я подтвердил, что работает, спасибо. Я также обнаружил, что когда вы добавляете квадратные скобки, то есть 'Binding (" [FirstName] ")' *, см. Мой предыдущий ответ ниже *, что он работает, но он значительно медленнее при привязке больших наборов данных. – JohnB

11

Я нашел решение, которое добавляет столбцы во время выполнения и связывается с 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; 
} 
+0

Вы нашли решение для этого тогда? – 321X

+2

Почему вы используете «[{0}]» в пути привязки? Это не работает для меня, но когда я просто использую имя без квадрата и колючек, тогда это работает? – smerlung

3

Если у вас уже есть привязка данных на месте, ответ John Myczek завершен.
Если нет, у вас есть как минимум 2 варианта, о которых я знаю, если вы хотите указать источник своих данных. (Тем не менее я не уверен, является ли это или нет в соответствии с большинством рекомендаций, как MVVM)

вариант 1: как Johnb сказал. Но я думаю, что вы должны использовать свою собственную коллекцию Defined вместо слабо типизированных 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; 

Если ваш тип имеет свойство ПгвЬЫате, вы можете сделать то, что указал Джон Мойчек.

DataGridTextColumn textColumn = new DataGridTextColumn(); 
dataColumn.Header = "First Name"; 
dataColumn.Binding = new Binding("FirstName"); 
dataGrid.Columns.Add(textColumn); 

Это, очевидно, не работает, если вы не знаете свойства, нужно будет показать в вашем DataGrid, но если это так, вы будете иметь больше проблем, чтобы иметь дело с, и я считаю, что это из scope здесь.

4

Редактировать: извините, у меня больше нет кода, упомянутого ниже. Это было аккуратное решение, хотя и сложное.


Я опубликовал пример проекта, описывающий, как использовать 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, чтобы «Пользователи» добавили еще один столбец в сетку.

+0

привет .. ваша ссылка не работает –

+0

@doblak Я нахожу, что это именно то, что мне нужно. У вас есть код вашего решения? – zhangz

+0

@zhangz обновил ответ, см. Этот пост для идеи DynamicPropertyDescriptor: https://jopinblog.wordpress.com/2007/05/12/dynamic-propertydescriptors-with-anonymous-methods/ – doblak

23

попробовать это, он работает на 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" }); 

     } 
+0

Есть ли способ добавить заголовок нескольких столбцов используя этот код? – Denis

16

У меня была такая же проблема. Добавление новых строк в 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); 

// редактировать:

Обратите внимание, что это не так, как следует использовать компонент, однако, это упрощает много, если вы только программно генерируется данные (например, в моем случае: последовательность функций и выход нейронной сети).

+1

именно то, что я искал. большое спасибо! –

0

Если у вас уже есть привязка данных на месте, ответ Джон Мьекек завершен. Если нет, у вас есть как минимум 2 варианта, о которых я знаю, если вы хотите указать источник своих данных.(Тем не менее я не уверен, является ли это или нет в соответствии с большинством рекомендаций, как MVVM)

Тогда вы просто привязать к коллекциям пользователей и столбцы генерироваться автоматически, как вы speficy их. Строки, переданные дескрипторам свойств, являются именами заголовков столбцов. Во время выполнения вы можете добавить больше PropertyDescriptors, чтобы «Пользователи» добавили еще один столбец в сетку.

+0

Пожалуйста, добавьте пример кода в свой ответ – Dethariel

Смежные вопросы