Insert blank row into Datagrid with dynamic columns
I am creating columns of my Silverlight DataGrid dynamically in code using a list like this:
private void BuildQuotationDGColumns(List<ProductCategory> ProdCatList)
{
// add a template column with drop down list of products
DataGridTemplateColumn ProductColumn = new DataGridTemplateColumn();
ProductColumn.Header="Choose Product";
ProductColumn.CellTemplate=(DataTemplate) Resources["ProductDDLTemplate"];
QuotationDG.Columns.Add(ProductColumn);
// for each entity in ProdCatList add a text column
foreach (ProductCategory ProdCat in ProdCatList)
{
DataGridTemplateColumn ProdCatColumn = new DataGridTemplateColumn();
ProdCatColumn.Header = ProdCat.Name;
ProdCatColumn.CellTemplate = (DataTemplate)Resources["MoneyTemplate"];
ProdCatColumn.CellEditingTemplate = (DataTemplate)Resources["MoneyEditingTemplate"];
QuotationDG.Columns.Add(ProdCatColumn);
}
insertDummyRow(ProdCatList);
}
I need to insert an empty row into my Datagrid using insertDummyRow. Since columns are dynamic and only known at runtime, I need to create an object whose attributes can be set at runtime.
I was thinking about converting my ProdCatList to a class so that instances of that class form grid rows, but I couldn't figure out how to do that conversion
EDIT:
Based on Bahman_Aries' solution below, I am trying to add data to my string, but I get an empty string and my data (column.Header.ToString ()) is not being added. Here's my code:
CultureInfo provider= new CultureInfo("en-US");
Object[] myrow= new Object[QuotationDG.Columns.Count];
int i=0;
foreach(DataGridColumn column in QuotationDG.Columns)
{
myrow[i] = Convert.ChangeType(column.Header.ToString(), typeof(object), provider);
i++;
}
MyData.Add(myrow);
QuotationDG.ItemsSource = MyData;
Can you point me to what I am doing wrong?
This is the implementation of the Grid templates:
<UserControl.Resources>
<DataTemplate x:Key="MoneyTemplate">
<TextBlock></TextBlock>
</DataTemplate>
<DataTemplate x:Key="MoneyEditingTemplate">
<TextBlock></TextBlock>
</DataTemplate>
<DataTemplate x:Key="ProductDDLTemplate">
<ComboBox />
</DataTemplate>
</UserControl.Resources>
source to share
Okay, let me clear up some of the confusion before we continue:
Since columns are dynamic and only known at runtime, I need to create an object whose attributes can be set at runtime.
Optionally, you can use a list objects
.
I was thinking about converting my ProdCatList to a class so that instances of that class will form grid rows
There is no need to create a complex data structure to insert an empty string into DataGrid
something as simple as QuotationDG.Items.Add("");
.
So, from what I understand, either you are exaggerating the problem or you are not providing enough information and I am oversimplifying it! (If so, please let me know so I can fix it right away).
Anyway, since you have defined CellEditingTemplate
, I am assuming that your grid cells are editable, so you cannot use QuotationDG.Items.Add
because that will prevent editing. Instead, you should define a list, add your data to it, and then use it like ItemsSource
yours DataGrid
:
// Your data source
ObservableCollection<object[]> MyData = new ObservableCollection<object[]>();
// Insert a blank row into the data source
private void insertDummyRow()
{
MyData.Add(new object[QuotationDG.Columns.Count]);
QuotationDG.ItemsSource = MyData;
}
Edit:
Since CellTemplates
there is no data binding in yours , nothing is visible in yours DataGrid
. For this to work when the columns are created dynamically, you also need to add the appropriate one DataBindings
:
// Sample drop down list of products to show
public ObservableCollection<string> ProductList = new ObservableCollection<string> { "Item1", "Item2", "Item3" };
private void BuildQuotationDGColumns(List<ProductCategory> ProdCatList)
{
// Define a DataGridComboBoxColumn
DataGridComboBoxColumn prodComboColumn = new DataGridComboBoxColumn();
// Bind this column to the first item of the DataGrid.ItemsSource (e.g. MyData[0])
prodComboColumn.SelectedItemBinding = new Binding("[0]");
// Set ProductList as the ItemsSource of DataGridComboBoxColumn
prodComboColumn.ItemsSource = ProductList;
prodComboColumn.Header = "Choose Product";
QuotationDG.Columns.Add(prodComboColumn);
// For each entity in ProdCatList add a text column
int i = 1;
foreach (ProductCategory ProdCat in ProdCatList)
{
// Define a DataGridTextColumn
DataGridTextColumn ProdCatColumn = new DataGridTextColumn();
ProdCatColumn.Header = ProdCat.Name;
// Bind this column to the i-th item of the DataGrid.ItemsSource (e.g. MyData[i])
ProdCatColumn.Binding = new Binding(string.Format("[{0}]", i));
QuotationDG.Columns.Add(ProdCatColumn);
i++;
}
insertDummyRow();
}
To see if the user interface is displaying any data, you can try a modified version of your add data routine:
private void Button_Click(object sender, RoutedEventArgs e)
{
CultureInfo provider = new CultureInfo("en-US");
Object[] myrow = new Object[QuotationDG.Columns.Count];
int i = 0;
foreach (DataGridColumn column in QuotationDG.Columns)
{
if (column is DataGridComboBoxColumn)
myrow[i] = Convert.ChangeType(ProductList[0], typeof(object), provider);
else
myrow[i] = Convert.ChangeType(column.Header.ToString(), typeof(object), provider);
i++;
}
MyData.Add(myrow);
QuotationDG.ItemsSource = MyData;
}
To have the data entered by the user also update the source (for example MyData
), set a breakpoint and mark MyData
for any changes after manually editing the data cell cells.
source to share