使用嵌套列表和动态列填充 DataGrid
Filling DataGrid using nested lists and dynamic columns
我有一个奇怪的数据模型,我正在尝试在数据网格中生成动态列并正确绑定项目。
我有一个要绑定到 DataGrid 并使用简单的 DataGridTextColumn 显示的 Row 对象列表。
<controls:DataGrid
Grid.Row="1"
x:Name="dataGrid"
ItemsSource="{x:Bind ViewModel.CurrentRows}"
我的 objective 是从第一行获取列列表并在设置绑定时构建我的网格列。我无法找出在 RowValue.value.
处绑定数据的正确方法
public TablePage()
{
InitializeComponent();
dataGrid.ItemsSource = ViewModel.CurrentRows;
foreach (Column column in ViewModel.CurrentRows.FirstOrDefault().Values.Select(x => x.key))
{
dataGrid.Columns.Add(new DataGridTextColumn()
{
Header = column.ColumnValidation.column_label,
Binding = new Binding() { Path = new PropertyPath("Values.value") }
});
}
}
在我的视图模型中我有:
public ObservableCollection<Row> CurrentRows
Row 对象如下所示:
public class Row: INotifyPropertyChanged
{
public List<RowValue> Values { get; set; } = new List<RowValue>();
public event PropertyChangedEventHandler PropertyChanged;
}
最后一个 RowValue 对象如下所示:
public class RowValue: INotifyPropertyChanged
{
public Column key { get; set; }
public string value { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
}
列如下所示:
public class Column
{
public string name;
public ColumnValidation ColumnValidation;
}
ColumnValidation 看起来像这样:
public class ColumnValidation
{
public string column_label;
public DataTypeEnum data_type;
public int width;
public int decimal_places;
public int display_order;
public string calculation_formula;
public string edit_style;
public string default_value;
public decimal? minimum_value;
public decimal? maximum_value;
public bool is_column_nullable = false;
public bool inherit_values = false;
public bool display_column = false;
public bool is_editable = false;
public int column_style;
public string code_table_name;
public string code_display_name;
public string code_data_column_name;
}
我的解决方案最终是使用我的列定义列表和行数据构建一个 DataTable。这是一个非常肮脏的解决方案,但它适合我的目的。我没有对网格进行任何编辑或保存,它只是用于显示数据。编辑发生在别处的对话框中。
public TablePage()
{
InitializeComponent();
// get list of columns
List<Column> columns = ViewModel.CurrentTableDefinition.Columns.OrderBy(x => x.ColumnValidation.display_order).ToList();
// create DataTable
DataTable dataTable = new DataTable();
dataTable.Columns.Add(new DataColumn() { ColumnName = "RowObject" }); // add column to store original row object
// add columns to datagrid and datatable
for (int i = 0; i < columns.Count; i++)
{
// add column to datagrid using the correct header label. bind using index of array.
dataGrid.Columns.Add(new DataGridTextColumn()
{
Header = columns[i].ColumnValidation.column_label,
Tag = columns[i].name,
Binding = new Binding() { Path = new PropertyPath("[" + i.ToString() + "]") }
});
// add corresponding column to datatable
dataTable.Columns.Add(new DataColumn() { ColumnName = columns[i].name });
}
// iterate through rows of data
foreach (Row row in ViewModel.CurrentRows)
{
// create new datatable row
DataRow dataRow = dataTable.NewRow();
// set the original row object
dataRow["RowObject"] = row;
// add data from each column in the row to the datatable row
for (int i = 0; i < columns.Count; i++)
{
// add column value to row
try
{
dataRow[i] = row.Values.Where(x => x.key.name == columns[i].name).FirstOrDefault().value;
}
catch (Exception ex)
{
dataRow[i] = null; // insert null if the table has columns defined for which there is no data in the dataset
}
}
// add datable row to datatable
dataTable.Rows.Add(dataRow);
}
// convert datatable to collection of 'object'
ObservableCollection<object> collection = new ObservableCollection<object>();
foreach(DataRow row in dataTable.Rows)
collection.Add(row.ItemArray);
// bind to datagrid
dataGrid.ItemsSource = collection;
}
我有一个奇怪的数据模型,我正在尝试在数据网格中生成动态列并正确绑定项目。
我有一个要绑定到 DataGrid 并使用简单的 DataGridTextColumn 显示的 Row 对象列表。
<controls:DataGrid
Grid.Row="1"
x:Name="dataGrid"
ItemsSource="{x:Bind ViewModel.CurrentRows}"
我的 objective 是从第一行获取列列表并在设置绑定时构建我的网格列。我无法找出在 RowValue.value.
处绑定数据的正确方法public TablePage()
{
InitializeComponent();
dataGrid.ItemsSource = ViewModel.CurrentRows;
foreach (Column column in ViewModel.CurrentRows.FirstOrDefault().Values.Select(x => x.key))
{
dataGrid.Columns.Add(new DataGridTextColumn()
{
Header = column.ColumnValidation.column_label,
Binding = new Binding() { Path = new PropertyPath("Values.value") }
});
}
}
在我的视图模型中我有:
public ObservableCollection<Row> CurrentRows
Row 对象如下所示:
public class Row: INotifyPropertyChanged
{
public List<RowValue> Values { get; set; } = new List<RowValue>();
public event PropertyChangedEventHandler PropertyChanged;
}
最后一个 RowValue 对象如下所示:
public class RowValue: INotifyPropertyChanged
{
public Column key { get; set; }
public string value { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
}
列如下所示:
public class Column
{
public string name;
public ColumnValidation ColumnValidation;
}
ColumnValidation 看起来像这样:
public class ColumnValidation
{
public string column_label;
public DataTypeEnum data_type;
public int width;
public int decimal_places;
public int display_order;
public string calculation_formula;
public string edit_style;
public string default_value;
public decimal? minimum_value;
public decimal? maximum_value;
public bool is_column_nullable = false;
public bool inherit_values = false;
public bool display_column = false;
public bool is_editable = false;
public int column_style;
public string code_table_name;
public string code_display_name;
public string code_data_column_name;
}
我的解决方案最终是使用我的列定义列表和行数据构建一个 DataTable。这是一个非常肮脏的解决方案,但它适合我的目的。我没有对网格进行任何编辑或保存,它只是用于显示数据。编辑发生在别处的对话框中。
public TablePage()
{
InitializeComponent();
// get list of columns
List<Column> columns = ViewModel.CurrentTableDefinition.Columns.OrderBy(x => x.ColumnValidation.display_order).ToList();
// create DataTable
DataTable dataTable = new DataTable();
dataTable.Columns.Add(new DataColumn() { ColumnName = "RowObject" }); // add column to store original row object
// add columns to datagrid and datatable
for (int i = 0; i < columns.Count; i++)
{
// add column to datagrid using the correct header label. bind using index of array.
dataGrid.Columns.Add(new DataGridTextColumn()
{
Header = columns[i].ColumnValidation.column_label,
Tag = columns[i].name,
Binding = new Binding() { Path = new PropertyPath("[" + i.ToString() + "]") }
});
// add corresponding column to datatable
dataTable.Columns.Add(new DataColumn() { ColumnName = columns[i].name });
}
// iterate through rows of data
foreach (Row row in ViewModel.CurrentRows)
{
// create new datatable row
DataRow dataRow = dataTable.NewRow();
// set the original row object
dataRow["RowObject"] = row;
// add data from each column in the row to the datatable row
for (int i = 0; i < columns.Count; i++)
{
// add column value to row
try
{
dataRow[i] = row.Values.Where(x => x.key.name == columns[i].name).FirstOrDefault().value;
}
catch (Exception ex)
{
dataRow[i] = null; // insert null if the table has columns defined for which there is no data in the dataset
}
}
// add datable row to datatable
dataTable.Rows.Add(dataRow);
}
// convert datatable to collection of 'object'
ObservableCollection<object> collection = new ObservableCollection<object>();
foreach(DataRow row in dataTable.Rows)
collection.Add(row.ItemArray);
// bind to datagrid
dataGrid.ItemsSource = collection;
}