2013-08-26 5 views
11

У меня есть Datagrid, который должен заполняться динамически.Заполнение Datagrid динамическими столбцами

TableLayout, как:

id | image | name | Description | Name-1 | Name-N 

Первые 4 колонки являются статическими остальные являются динамическими. Пользователь должен иметь возможность добавлять столько пользователей, сколько захочет.

Я пытаюсь сравнить данные нескольких пользователей, помещая их рядом друг с другом в таблицу.

Прямо сейчас у меня есть Listbox whitch содержит имена динамически генерируемых столбцов и метод, который заполняет статические столбцы. Я также могу загрузить данные для каждого пользователя. теперь мне нужно объединить их в один большой стол.

Основная проблема: как разместить «Userdata» и статический контент в одном datagrid.

+0

Это единственный способ отображения этой информации? –

+0

Я не уверен, что вы просите. – Wr4thon

+0

Йоханнес видит мой ответ, так что вы можете понять, почему я спрашивал об этом. –

ответ

20

Есть по крайней мере три способа сделать это:

  1. Изменить столбцы в DataGrid вручную из кода за
  2. Использовать DataTable как ItemsSource *
  3. Использовать CustomTypeDescriptor

    * рекомендуется для простоты


1-й подход: использовать код для создания столбцов DataGrid во время выполнения. Это просто реализовать, но, может быть, это немного хаки, особенно если вы используете MVVM. Таким образом, вы бы ваш DataGrid с фиксированными столбцами:

<DataGrid x:Name="grid"> 
    <DataGrid.Columns> 
     <DataGridTextColumn Binding="{Binding id}" Header="id" /> 
     <DataGridTextColumn Binding="{Binding image}" Header="image" /> 
    </DataGrid.Columns> 
</DataGrid> 

Если у вас есть свои «имена» готов, а затем изменить сетку путем добавления/удаления столбцов, например:

// add new columns to the data grid 
void AddColumns(string[] newColumnNames) 
{ 
    foreach (string name in newColumnNames) 
    { 
     grid.Columns.Add(new DataGridTextColumn { 
      // bind to a dictionary property 
      Binding = new Binding("Custom[" + name + "]"), 
      Header = name 
     }); 
    } 
} 

Вы хотите создать класс-оболочку, который должен содержать исходный класс, а также словарь, содержащий пользовательские свойства. Допустим, что ваш основной класс строка «User», то вы хотели бы класс обертку что-то вроде этого:

public class CustomUser : User 
{ 
    public Dictionary<string, object> Custom { get; set; } 

    public CustomUser() : base() 
    { 
     Custom = new Dictionary<string, object>(); 
    } 
} 

заселить ItemsSource с коллекцией этого нового класса «CustomUser»:

void PopulateRows(User[] users, Dictionary<string, object>[] customProps) 
{ 
    var customUsers = users.Select((user, index) => new CustomUser { 
     Custom = customProps[index]; 
    }); 
    grid.ItemsSource = customUsers; 
} 

Так связывая их вместе, например:

var newColumnNames = new string[] { "Name1", "Name2" }; 
var users = new User[] { new User { id="First User" } }; 
var newProps = new Dictionary<string, object>[] { 
    new Dictionary<string, object> { 
     "Name1", "First Name of First User", 
     "Name2", "Second Name of First User", 
    }, 
}; 
AddColumns(newColumnNames); 
PopulateRows(users, newProps); 

второй подход: использовать DataTable. Это использует инфраструктуру настраиваемого типа под капотом, но ее проще в использовании.Просто привязать DataGrid-х ItemsSource к DataTable.DefaultView собственности:

<DataGrid ItemsSource="{Binding Data.DefaultView}" AutoGenerateColumns="True" /> 

Затем вы можете определить столбцы, как вам нравится, например:

Data = new DataTable(); 

// create "fixed" columns 
Data.Columns.Add("id"); 
Data.Columns.Add("image"); 

// create custom columns 
Data.Columns.Add("Name1"); 
Data.Columns.Add("Name2"); 

// add one row as an object array 
Data.Rows.Add(new object[] { 123, "image.png", "Foo", "Bar" }); 

третий подход: делают использование расширяемости .Net. В частности, используйте CustomTypeDescriptor. Это позволяет создать пользовательский тип во время выполнения; который, в свою очередь, позволяет вам сообщить DataGrid, что ваш тип имеет свойства «Name1», «Name2», ... «NameN» или любые другие, которые вы хотите. См. here для простого примера этого подхода.

+2

Я нашел подход DataTable самым простым и эффективным решением. –

+0

Кто-нибудь успешно создал автогенерированные столбцы в DataGrid, используя метод 3? У меня уже есть определенный дескриптор настраиваемого типа, я могу просто привязать его свойства, но автогенерирующие столбцы не работают. – Jesse

+0

Что делать, если мы хотим редактировать и обновлять значения в одной и той же сетке данных? – Shelly

0

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

+0

Ну, я не думаю, что это решит мою проблему. У меня есть одна большая таблица, содержащая некоторые данные (без разницы), теперь мне нужно сравнить несколько имен с записями. Поэтому для каждой записи мне нужно «N» больше Colummns, чтобы сравнить двух или более лиц. е. г. : Запись 1: 1; tmp.png; Foo; bar; успешно, не выполнено Запись 2: 2; tmp2.png; Foo1; bar2; не удалось; – Wr4thon

4

2-й подход: используйте DataTable. Это использует инфраструктуру настраиваемого типа под капотом, но ее проще в использовании. Просто привяжите элемент ItemsSource DataGrid к свойству DataTable.DefaultView:

Это почти сработало, но вместо привязки к свойству свойства DataTable.DefaultView я создал свойство типа DataView и привязано к нему.

<DataGrid ItemsSource="{Binding DataView, Mode=TwoWay}" AutoGenerateColumns="True" />

Это позволяет связывание быть два пути, привязка к DataTable.DefaultView не может быть TwoWay связывания. В Модельное

public DataView DataView 
    { 
     get { return _dataView; } 
     set 
     { 
      _dataView = value; 
      OnPropertyChanged("DataView"); 
     } 
    } 

С этой установкой я мог не только определить столбцы динамически, когда View Model инициализируется, но может обновлять и изменять данные таблицы динамически в любое время. При использовании подхода, определенного МакГарнаглом выше, схема представления не обновлялась, когда DataTable был обновлен новым источником данных.

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