программно добавлять столбцы и строки в WPF Datagrid - PullRequest
67 голосов
/ 01 апреля 2009

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

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

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

Ответы [ 7 ]

68 голосов
/ 01 апреля 2009

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

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

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

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

За дополнительной информацией обращайтесь к на форуме WPG DataGrid.

27 голосов
/ 05 июля 2012

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

        }
20 голосов
/ 22 ноября 2013

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

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

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

11 голосов
/ 19 января 2011

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

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 в «Пользователи», добавить еще один столбец в сетку.

3 голосов
/ 19 мая 2011

Если у вас уже есть привязка данных, Джон Мычек ответ завершен.
Если нет, у вас есть как минимум 2 варианта, которые я знаю, если вы хотите указать источник ваших данных. (Однако я не уверен, является ли это в соответствует большинству рекомендаций, например, 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, но если это так, у вас будет больше проблем, и я считаю, что это выходит за рамки.

0 голосов
/ 02 октября 2015

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

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

...