Ответ 1
Существует как минимум три способа сделать это:
- Модифицировать столбцы DataGrid вручную из кода
- Используйте DataTable в качестве источника Items *
-
Используйте 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
});
}
}
Вам нужно создать класс-оболочку, который должен содержать исходный класс, а также словарь, содержащий пользовательские свойства. Скажем, ваш основной класс строк - "Пользователь", тогда вам понадобится класс-оболочка:
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" или любые другие, которые вы хотите. См. здесь для простого примера этого подхода.