Как сериализовать и десериализовать ObservableCollection с контекстом данных DataTable в json файл
Подскажите пожалуйста.
У меня есть ObservableCollection<DataGrid> DataGrids {get; set;}
, который отображаю в визуальном элементе xaml ItemsControl.
С помощью команды я добавляю в эту коллекцию DataGrid с контекстом данных DataTable.
Command = ReactiveCommand.Create(() =>
{
DataGrid datagrid = new();
DataTable datatable = new();
for (int j = 0; j < 4; j++) datatable.Columns.Add(Subject[j]);
datagrid.ItemsSource = datatable.DefaultView;
DataGrids.Add(datagrid);
});
Названия для колонок
public List<string> Subject = new List<string>() { "Математика", "Физика", "Химия", "Биология", "Геометрия" };
Как можно сериализовать ObservableCollcetion<DataGrid> DataGrids {get; set;}
, так чтобы сериализовывались данные строк и названия колонок в json файл, и можно было десериализовать обратно при входе в окно, чтобы также все оставалось в порядке названия колонок и данные строк.
Пробовал дергать свойство ItemsSource через Linq, но падают исключения, или сериализация неправильная, также десериализация кривая. Подскажите как сделать, может другой подход нужен?
Миниатюра. Колонок может быть разное количество, данные - просто строки. Сериализую в json файл в директорию.
xaml код.
<ItemsControl ItemsSource="{Binding DataGrids}"/>
Ответы (1 шт):
Начнём с самого главного - контролов не должно быть в данных.
ObservableCollection<DataTable> Tables { get; } = new();
<ItemsControl ItemsSource="{Binding Tables}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<DataGrid ItemsSource="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Здесь же в XAML и разные настройки для DataGrid
можно будет прописать.
Теперь создание таблицы.
Command = ReactiveCommand.Create(() =>
{
DataTable datatable = new();
foreach (string subject in Subject)
{
datatable.Columns.Add(new DataColumn(subject, typeof(string),
{
AllowDBNull = false,
DefaultValue = ""
}));
}
Tables.Add(datatable);
});
Теперь сериализация в файл
public void SerializeDataTable(string path, DataTable table)
{
Dictionary<string, string[]> data = new();
DataRow[] rows = table.Select();
foreach (string name in table.Columns.Select(x => x.ColumnName))
{
data[name] = rows.Select(row => (string)row[name])).ToArray();
}
string json = JsonSerializer.Serialize(data);
File.WriteAllText(path, json);
}
И в обратную сторону
public DataTable DeserializeDataTable(string path)
{
string json = File.ReadAllText(path);
Dictionary<string, string[]> data = JsonSerializer.Deserialize<Dictionary<string, string[]>>(json);
DataTable table = new();
foreach (string subject in data.Keys)
{
table.Columns.Add(new DataColumn(subject, typeof(string),
{
AllowDBNull = false,
DefaultValue = ""
}));
}
for (int i = 0; i < data[data.Keys[0]].Length; i++)
{
string[] rowData = data.Values.Select(x => x[i]).ToArray();
table.Rows.Add(rowData);
}
return table;
}
Можно считать что это решение "в лоб", и по-взрослому это делается через JSON конвертеры. Но так тоже сработает, у вас же не будет миллионов строк или колонок в этих таблицах, поэтому не должно тормозить.