This is a migrated thread and some comments may be shown as answers.

Using list of Dictionary as datasource for DetailTableViews?

3 Answers 592 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Anders
Top achievements
Rank 1
Anders asked on 14 Sep 2016, 11:27 AM

In a telerik:RadGrid, I specify that every line will have a detail table:

<telerik:RadGrid ID="grd" AutoGenerateColumns="False" runat="server"
    OnDetailTableDataBind="grd_OnDetailTableDataBind" AllowMultiRowSelection="True">
  <MasterTableView DataKeyNames="id1,id2">
    <Columns>
      <telerik:GridClientSelectColumn UniqueName="DetailCheckColumn"/>
      <telerik:GridBoundColumn HeaderText="Date" DataField="foo"/>
      <telerik:GridBoundColumn HeaderText="Time" DataField="bar"/>
      <telerik:GridBoundColumn HeaderText="Activity" DataField="xod"/>
    </Columns>
    <DetailTables>
      <telerik:GridTableView ShowHeadersWhenNoRecords="True"
          DataKeyNames="id" Name="Child"/>
    </DetailTables>
  </MasterTableView>
  <ClientSettings>
    <Selecting AllowRowSelect="true"/>
  </ClientSettings>
</telerik:RadGrid>

In the handler for the OnDetailTableDataBind event, I specify the data source for the DetailTableView. The handler is called when a line is expanded. Setting a list of anonymous objects as data source works fine, but a list of Dictionary will not.

I get a yellow page, It seems like the grid table view tries to find a property id of Dictionary

DataBinding: System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] does not have a property with the name id.

If I remove the DataKeyNames attribute in the detail table, I will get a detail table with the correct number of lines, but the fields will be all blank (screenshot is attached).

The event handler where I create the detail table for each expanded line. Observe that I name columns c1, c2 etc. I create the columns in the first loop round.

protected void grd_OnDetailTableDataBind(object sender,
    GridDetailTableDataBindEventArgs e)
{
  var tv = e.DetailTableView;
  var parentItem = e.DetailTableView.ParentItem;
 
  var bis = dal.get_booking_informations();
 
  tv.Columns.Add(new GridClientSelectColumn());
 
  var columnNameDict = new Dictionary<string,string>();
 
  var firstDict = true;
  var dicts = bis.GroupBy(bi=>bi.platsBokadID).Select(group =>
  {
    var dict = new Dictionary<string, string>();
 
    dict["id"] = "" + group.Key;
 
    var list = group.ToList();
 
    if (firstDict)
    {
      firstDict = false;
 
      var num = 0;
      var columns = list.Select(header=>
      {
        var shortName = "c" + ++num;
        columnNameDict[header.HeaderName] = shortName;
 
        return new GridBoundColumn
        {
          DataField = shortName,
          HeaderText = header.HeaderName
        };
      });
 
      foreach(var column in columns)
        tv.Columns.Add(column);
    }
 
    foreach(var header in list)
    {
      var shortName = columnNameDict[header.HeaderName];
      dict[shortName] = header.Value;
    }
 
    return dict;
  });
 
  tv.DataSource = dicts;
}

I have also tried to use dynamic objects instead of Dictionaries (with the same result):

protected void grdActivitiesToCopy_OnDetailTableDataBind(object sender, GridDetailTableDataBindEventArgs e)
{
        var tv = e.DetailTableView;
        var parentItem = e.DetailTableView.ParentItem;
 
        var bis = dal.get_booking_informations();
 
        tv.Columns.Add(new GridClientSelectColumn());
 
        var columnNameDict = new Dictionary<string,string>();
 
        var firstDict = true;
        var dicts = bis.GroupBy(bi=>bi.platsBokadID).Select(group =>
        {
                var dict = new Dictionary<string, object>();
 
                dict["id"] = "" + group.Key;
 
                var list = group.ToList();
 
                if (firstDict)
                {
                        firstDict = false;
 
                        var num = 0;
                        var columns = list.Select(header=>
                        {
                                var shortName = "c" + ++num;
                                columnNameDict[header.HeaderName] = shortName;
 
                                return new GridBoundColumn
                                {
                                        DataField = shortName,
                                        HeaderText = header.HeaderName
                                };
                        });
 
                        foreach(var column in columns)
                                tv.Columns.Add(column);
                }
 
                var eo = new ExpandoObject();
                var eoColl = (ICollection<KeyValuePair<string, object>>)eo;
                foreach(var header in list)
                {
                        var shortName = columnNameDict[header.HeaderName];
                        dict[shortName] = header.Value;
                }
 
                foreach (var kvp in dict)
                {
                        eoColl.Add(kvp);
                }
 
                dynamic eoDynamic = eo;
 
                return eoDynamic;
        }).ToList();
 
        tv.DataSource = dicts;
}

 

3 Answers, 1 is accepted

Sort by
0
Eyup
Telerik team
answered on 19 Sep 2016, 06:48 AM
Hello Ingemar,

The data source of the grid should contain properties as fields. In your case you can use anonymous types and LINQ projection. Return the following collection instead of Dictionary:
e.DetailTableView.DataSource=bis.Select(x=>new { FieldID = some id, FieldString = "some value",  FieldDate = some date, etc.});

That should do the trick.

Regards,
Eyup
Telerik by Progress
Do you need help with upgrading your ASP.NET AJAX, WPF or WinForms projects? Check the Telerik API Analyzer and share your thoughts.
0
Anders
Top achievements
Rank 1
answered on 03 Oct 2016, 07:47 AM
But how will that anonymous object be able to contain a dynamic number of properties then?
0
Eyup
Telerik team
answered on 06 Oct 2016, 06:47 AM
Hello Ingemar,

This depends solely on your code-behind logic and it is not related specifically to RadGrid control functionality. If you plan to dynamically change the fields and columns of the grid, you can check the following article:
http://www.telerik.com/help/aspnet-ajax/grid-changing-structure-dynamically.html

Regards,
Eyup
Telerik by Progress
Do you need help with upgrading your ASP.NET AJAX, WPF or WinForms projects? Check the Telerik API Analyzer and share your thoughts.
Tags
Grid
Asked by
Anders
Top achievements
Rank 1
Answers by
Eyup
Telerik team
Anders
Top achievements
Rank 1
Share this question
or