3

I create the columns of my Silverlight DataGrid dynamically in the code behind using a List as follows:

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 a blank row in my Datagrid using insertDummyRow. Since the columns are dynamic and are only known in runtime, I need to create an entity whose attributes can be set in run time.

I thought of converting my ProdCatList into a Class, so that instances of this class would form the grid rows, but I couldn't understand how to do this conversion

EDIT:

Based on Bahman_Aries's solution below, I'm trying to add data into my row but I'm getting empty row and my data (column.Header.ToString()) isn't 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 on what i'm doing wrong?

This is the implementation for 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>
user3340627
  • 3,023
  • 6
  • 35
  • 80
  • What is the intention for having the blank row? Does the user enter anything into the blank row? What does a row of your grid represent? – Martin Jun 15 '15 at 15:45
  • @Martin Yes, exactly. What I need to do is let the user enter values into the row so that I can insert these values into CRM 2015. – user3340627 Jun 16 '15 at 08:38
  • And will this grid hold a single row during runtime and not more than one row? – Martin Jun 16 '15 at 09:05
  • @Martin it might hold more than 1 row, the user gets to add the rows he wants during run time. I just wanted to experiment adding a single row just to test if it's going to work. – user3340627 Jun 16 '15 at 12:34
  • @user3340627 I changed the title if you don't mind. – Bahman_Aries Jun 17 '15 at 07:50

1 Answers1

1

Okey, let me clear up some confusion before we proceed:

Since the columns are dynamic and are only known in runtime, I need to create an entity whose attributes can be set in run time.

Not necessarily, you can use a list of objects.

I thought of converting my ProdCatList into a Class, so that instances of this class would form the grid rows

There is no need to create a complex data structure just to insert a blank row into the DataGrid, something as simple as QuotationDG.Items.Add(""); will do.

So from what I understand, either you're overcomplicating the issue or you did not provide enough information and I'm oversimplifying it! (If so please let me know so I can correct this straight away).

Anyhow, Since you defined a CellEditingTemplate I assume your grid cells are editable, therefore you can not use QuotationDG.Items.Add because it'll prevent editing. Instead you should define a list, add your data to it and then use it as ItemsSource of your 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 there is no data-binding in your CellTemplates, nothing can be seen in your DataGrid. For this to work, when columns are creating dynamically you need to add corresponding DataBindings as well:

// 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 UI shows any data, you can try my modified version of your add-data procedure:

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 be sure that data entered by user is going to update the source (e.g. MyData) as well, set a break-point and check MyData for any changes after editing data-grid cells manually.

Bahman_Aries
  • 4,658
  • 6
  • 36
  • 60
  • Thanks a lot for your reply, however I still have one concern, the user is the one who is going to add data into list in run time, will this structure enable me to do update with what the user entered? – user3340627 Jun 16 '15 at 12:54
  • I also can't use the example in the Button_Click function to test adding data because the number of columns are unknown, i need to be adding the data in some sort of For Loop to add sample data in each column. I'm not sure if this is possible. I test Button_Click function as is, but it ended up showing empty rows instead of having any data. – user3340627 Jun 16 '15 at 13:03
  • About your first comment, If what you asked means data entered by the user is accessible for you, then the answer is yes. `MyData` will update when user insert/update data. – Bahman_Aries Jun 16 '15 at 13:08
  • for your next comment, I wrote Button_Click method to show a simple example on how it's possible to add more rows to the data-grid, It's not meant to show a solution for inserting data in general, moreover you didn't ask for such a solution and from what I understand, data is going to be inserted only by the user right? – Bahman_Aries Jun 16 '15 at 13:14
  • If my solution doesn't solve your issue, please share more information on the problem and i'll be happy to help. – Bahman_Aries Jun 16 '15 at 13:16
  • Yes, I didn't ask for it from the start, I just wanted to test the code in your solution. I'm trying it out once more and will be giving you the feedback. Thanks a lot for your cooperation. – user3340627 Jun 16 '15 at 13:17
  • Concerning the input to the grid, actually the requirement is somehow complicated, I will do both things, the user will enter data in the empty row, but I also got some static columns in the grid that I will be filling during runtime based on the user's input – user3340627 Jun 16 '15 at 13:18
  • I just test your code and it worked fine. could you also show how you've implemented `MoneyTemplate` and `MoneyEditingTemplate`? Is there any data-bindings? – Bahman_Aries Jun 16 '15 at 13:30
  • I updated my question, no i didn't add any bindings. – user3340627 Jun 16 '15 at 13:33
  • your cell templates can't show any data. I have to go now but I'll be back tomorrow. In the meantime you may want to check out [this solution](http://stackoverflow.com/a/7676938/1648849) on how to apply a `DataTemplate` to data-grid cells in run-time. – Bahman_Aries Jun 16 '15 at 14:05
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/80751/discussion-between-user3340627-and-bahman-aries). – user3340627 Jun 17 '15 at 08:52