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

How to use List<T> as Source in Hierarchy Grid

7 Answers 90 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Jon
Top achievements
Rank 1
Jon asked on 13 May 2011, 09:45 PM
Greetings,

I have an odd request. I am making a 3-table hierarchy grid and I need the for the data source of the 3rd grid, to use a List from it's parent grid( the 2nd grid in the hierarchy).

Grid A - datasource is a List<EventDto> called "results"

Grid B - datasource is one or more records of type List<EntityDto> called "details." Details has several fields that are displayed, and it also has another List, of type <EntityRowDto>, and it is possible to have one or more of these (which is why I need a 3rd grid).

So how do I pull out all <EntityRowDto> records for a given detail and set it as the datasource for Grid C?

ASP.NET Markup for the grid:
 <telerik:RadGrid ID="radGridNewAuditLog" runat="server" AutoGenerateColumns="False"
                     GridLines="None" Skin="Office2007" AllowFilteringByColumn="True" AllowPaging="True"
                     AllowSorting="True" OnNeedDataSource="radGridNewAuditLog_NeedDataSource" EnableLinqExpressions="False"
                     Font-Bold="False" Font-Italic="False" Font-Overline="False" Font-Size="Small"
                     Font-Strikeout="False" Font-Underline="False"
                     OnDetailTableDataBind="radGridNewAuditLog_DetailTableDatabind"
                     OnPreRender="radGridNewAuditLog_PreRender">
      <ClientSettings Selecting-AllowRowSelect="false" EnableRowHoverStyle="true">
          <ClientEvents />
      </ClientSettings>
      <PagerStyle Position="TopAndBottom" />
      <MasterTableView PageSize="20" EnableNoRecordsTemplate="true" ShowHeadersWhenNoRecords="true"
          Font-Bold="False" Font-Italic="False" Font-Overline="False" Font-Size="Small"
          Font-Strikeout="False" Font-Underline="False" DataKeyNames="SessionId" HierarchyDefaultExpanded="true"
          HierarchyLoadMode="ServerOnDemand">
          <DetailTables>
            <telerik:GridTableView Name="Details" DataKeyNames="EntityId" HierarchyDefaultExpanded="true">
                <Columns>
                <telerik:GridBoundColumn DataField="EntityId" UniqueName="EntityId" Visible="true"/>
                <telerik:GridBoundColumn DataField="EntityName" HeaderText="Entity Name" UniqueName="EntityName"
                                     CurrentFilterFunction="Contains" AutoPostBackOnFilter="true"/>
                <telerik:GridBoundColumn DataField="EntitySystem" HeaderText="System" UniqueName="EntitySystem"
                                     CurrentFilterFunction="Contains" AutoPostBackOnFilter="true"/>
                </Columns>
            </telerik:GridTableView>
          </DetailTables>
          <RowIndicatorColumn>
              <HeaderStyle Width="20px"></HeaderStyle>
          </RowIndicatorColumn>
          <ExpandCollapseColumn>
              <HeaderStyle Width="20px"></HeaderStyle>
          </ExpandCollapseColumn>
          <Columns>
            <telerik:GridBoundColumn DataField="EventType" HeaderText="Event" UniqueName="EventType"
                                     CurrentFilterFunction="Contains" AutoPostBackOnFilter="true"/>
            <telerik:GridBoundColumn DataField="Username" HeaderText="User" UniqueName="Username"
                                     CurrentFilterFunction="Contains" AutoPostBackOnFilter="true" />
            <telerik:GridBoundColumn DataField="Description" HeaderText="Description" UniqueName="Description"
                                     AllowFiltering="false" />
            <telerik:GridBoundColumn DataField="InitiatingApp" HeaderText="Initiating App" UniqueName="InitiatingApp"
                                     CurrentFilterFunction="Contains" AutoPostBackOnFilter="true" />
            <telerik:GridBoundColumn DataField="EventId" UniqueName="EventId" Visible="false"/>
            <telerik:GridBoundColumn HeaderText="Created On" ItemStyle-Width="160px" UniqueName="CreatedOn" DataField="CreatedOn"
                            AllowFiltering="false" DataType="System.DateTime" DataFormatString="{0:MM/dd/yyyy hh:mm tt CT}">
            </telerik:GridBoundColumn>
          </Columns>
      </MasterTableView>
    </telerik:RadGrid>

C# CodeBehind:
protected void radGridNewAuditLog_NeedDataSource(object sender, GridNeedDataSourceEventArgs e)
 {
        if (!e.IsFromDetailTable)
            SetGridDataSource();
 }

protected void radGridNewAuditLog_DetailTableDatabind(object sender, Telerik.Web.UI.GridDetailTableDataBindEventArgs e)
        {
            GridDataItem dataItem = (GridDataItem)e.DetailTableView.ParentItem;
            List<EntityDto> details = new List<EntityDto>();
            switch (e.DetailTableView.Name)
            {
                case "Details":
                    {
                        
                        LoggingRepository logrepodetails = new LoggingRepository();
                        TableCell cellEventId = dataItem["EventId"];
                        string strEventId = cellEventId.Text;
                        int eventId = -1;
                        int.TryParse(strEventId, out eventId);
                        if (eventId <= 0)
                            return;
                        details = logrepodetails.GetEventDetails(eventId);
                        
                        e.DetailTableView.DataSource = details;

                
                        break;
                    }

            }
            
        }


 protected void SetGridDataSource()
        {
            LoggingRepository logrepo = new LoggingRepository();
            List<string> et = new List<string>();
            List<EventDto> results=null;
           

            if (_userid == null)
                results = logrepo.GetEvents(new Guid(), et, (DateTime)FromDateText.SelectedDate, (DateTime)ToDateText.SelectedDate); //All are optional. If dates are blank I default to last 5 days
            else
            {
                Guid gUserId = new Guid(_userid);
                results = logrepo.GetEvents(gUserId, et, (DateTime)FromDateText.SelectedDate, (DateTime)ToDateText.SelectedDate); //All are optional. If dates are blank I default to last 5 days
            }

            if (results.Count == 0)
                return;
            radGridNewAuditLog.DataSource = results;
            
        }

 protected void radGridNewAuditLog_PreRender(object sender, EventArgs e)
        {
            HideExpandColumnRecursive(radGridNewAuditLog.MasterTableView);
        }

        public void HideExpandColumnRecursive(GridTableView tableView)
        {
            GridItem[] nestedViewItems = tableView.GetItems(GridItemType.NestedView);
            foreach (GridNestedViewItem nestedViewItem in nestedViewItems)
            {
                foreach (GridTableView nestedView in nestedViewItem.NestedTableViews)
                {
                    if (nestedView.Items.Count == 0)
                    {
                        TableCell cell = nestedView.ParentItem["ExpandColumn"];
                        cell.Controls[0].Visible = false;
                        nestedViewItem.Visible = false;
                    }
                    if (nestedView.HasDetailTables)
                    {
                        HideExpandColumnRecursive(nestedView);
                    }
                }
            }
        }

7 Answers, 1 is accepted

Sort by
0
Jon
Top achievements
Rank 1
answered on 16 May 2011, 01:30 PM
Anyone have a suggestion?
0
Elliott
Top achievements
Rank 2
answered on 16 May 2011, 02:59 PM
I think the simplest way would be to give the third grid its own datasource - build it from the same store as the other 2 grids
you'll have to be careful about keeping the data sources in sync
0
Jon
Top achievements
Rank 1
answered on 16 May 2011, 03:26 PM
Marianne,

Thanks for the reply. I got it working, so I will share the solution below:

ASPX Markup for grid:
  <telerik:RadGrid ID="radGridNewAuditLog" runat="server" AutoGenerateColumns="False"
                     GridLines="None" Skin="Office2007" AllowFilteringByColumn="True" AllowPaging="True"
                     AllowSorting="True" OnNeedDataSource="radGridNewAuditLog_NeedDataSource" EnableLinqExpressions="False"
                     Font-Bold="False" Font-Italic="False" Font-Overline="False" Font-Size="Small"
                     Font-Strikeout="False" Font-Underline="False"
                     OnDetailTableDataBind="radGridNewAuditLog_DetailTableDatabind"
                     OnPreRender="radGridNewAuditLog_PreRender">
      <ClientSettings Selecting-AllowRowSelect="false" EnableRowHoverStyle="true">
          <ClientEvents />
      </ClientSettings>
      <PagerStyle Position="TopAndBottom" />
      <MasterTableView PageSize="20" EnableNoRecordsTemplate="true" ShowHeadersWhenNoRecords="true"
          Font-Bold="False" Font-Italic="False" Font-Overline="False" Font-Size="Small"
          Font-Strikeout="False" Font-Underline="False" DataKeyNames="SessionId" HierarchyDefaultExpanded="true"
          HierarchyLoadMode="ServerOnDemand">
          <DetailTables>
            <telerik:GridTableView Name="Details" DataKeyNames="EntityId" HierarchyDefaultExpanded="true">
                <DetailTables>
                    <telerik:GridTableView Name="EntityRow" HierarchyDefaultExpanded="true">
                        <Columns>
                            <telerik:GridBoundColumn DataField="FieldName" UniqueName="FieldName" Visible="true"/>
                            <telerik:GridBoundColumn DataField="OldValue" UniqueName="OldValue" Visible="true"/>
                            <telerik:GridBoundColumn DataField="NewValue" UniqueName="NewValue" Visible="true"/>
                        </Columns>
                    </telerik:GridTableView>
                </DetailTables>

                <Columns>
                <telerik:GridBoundColumn DataField="EntityId" UniqueName="EntityId" Visible="true"/>
                <telerik:GridBoundColumn DataField="EntityName" HeaderText="Entity Name" UniqueName="EntityName"
                                     CurrentFilterFunction="Contains" AutoPostBackOnFilter="true"/>
                <telerik:GridBoundColumn DataField="EntitySystem" HeaderText="System" UniqueName="EntitySystem"
                                     CurrentFilterFunction="Contains" AutoPostBackOnFilter="true"/>
                </Columns>
            </telerik:GridTableView>
          </DetailTables>

          <RowIndicatorColumn>
              <HeaderStyle Width="20px"></HeaderStyle>
          </RowIndicatorColumn>
          <ExpandCollapseColumn>
              <HeaderStyle Width="20px"></HeaderStyle>
          </ExpandCollapseColumn>
          <Columns>
            <telerik:GridBoundColumn DataField="EventType" HeaderText="Event" UniqueName="EventType"
                                     CurrentFilterFunction="Contains" AutoPostBackOnFilter="true"/>
            <telerik:GridBoundColumn DataField="Username" HeaderText="User" UniqueName="Username"
                                     CurrentFilterFunction="Contains" AutoPostBackOnFilter="true" />
            <telerik:GridBoundColumn DataField="Description" HeaderText="Description" UniqueName="Description"
                                     AllowFiltering="false" />
            <telerik:GridBoundColumn DataField="InitiatingApp" HeaderText="Initiating App" UniqueName="InitiatingApp"
                                     CurrentFilterFunction="Contains" AutoPostBackOnFilter="true" />
            <telerik:GridBoundColumn DataField="EventId" UniqueName="EventId" Visible="false"/>
            <telerik:GridBoundColumn HeaderText="Created On" ItemStyle-Width="160px" UniqueName="CreatedOn" DataField="CreatedOn"
                            AllowFiltering="false" DataType="System.DateTime" DataFormatString="{0:MM/dd/yyyy hh:mm tt CT}">
            </telerik:GridBoundColumn>
          </Columns>
      </MasterTableView>
    </telerik:RadGrid>

Codebehind for DetailTableDataBind:
        protected void radGridNewAuditLog_DetailTableDatabind(object sender, Telerik.Web.UI.GridDetailTableDataBindEventArgs e)
        {
            GridDataItem dataItem = (GridDataItem)e.DetailTableView.ParentItem;
            List<EntityDto> details = new List<EntityDto>();
            switch (e.DetailTableView.Name)
            {
                case "Details":
                    {
                        LoggingRepository logrepodetails = new LoggingRepository();
                        TableCell cellEventId = dataItem["EventId"];
                        string strEventId = cellEventId.Text;
                        int eventId = -1;
                        int.TryParse(strEventId, out eventId);
                        if (eventId <= 0)
                            return;
                        details = logrepodetails.GetEventDetails(eventId);
                        e.DetailTableView.DataSource = details;
                        break;
                    }
                case "EntityRow":
                    {
                        List<EntityDto> rowDetails = new List<EntityDto>();
                        string strEntityId = dataItem.GetDataKeyValue("EntityId").ToString();
                        rowDetails = (List<EntityDto>)e.DetailTableView.ParentItem.OwnerTableView.DataSource; //this is how to get back to the List that is embedded in the parent

                        List<EntityRowDto> entityRows = new List<EntityRowDto>();
                        foreach (EntityDto rows in rowDetails)
                        {
                            if (rows.EntityId.ToString() == strEntityId)
                            {
                                foreach (EntityRowDto erdto in rows.EntityRows)
                                {
                                    entityRows.Add(erdto);
                                }
                                break;
                            }
                            

                        }
                        e.DetailTableView.DataSource = entityRows;
                        break;
                    }

            }
            
        }
0
Elliott
Top achievements
Rank 2
answered on 16 May 2011, 04:06 PM
pretty slick - and kinda simple
iterate through the upper 2 grids when you need to build the third
I noticed you instantiated a List for the third table

thanks-I built a 3 tier grid but used datasets built with ADO
it doesn't look like there is any updating so no synchronization issues
0
Jon
Top achievements
Rank 1
answered on 16 May 2011, 04:15 PM
I do prefer ADO datasets, because they make detail binding easy. I was stuck with the data structure so I had to make it work. One more thing. To get paging to work on the 3rd detail table, I had to modify the code to acquire the parent data source, every time someone pages forward or backwards. For someone reason, the datasource becomes null when someone pages forward/backward.

The final code for DetailTableDatabind is below:

protected void radGridNewAuditLog_DetailTableDatabind(object sender, Telerik.Web.UI.GridDetailTableDataBindEventArgs e)
        {
            GridDataItem dataItem = (GridDataItem)e.DetailTableView.ParentItem;
            List<EntityDto> details = new List<EntityDto>();
            switch (e.DetailTableView.Name)
            {
                case "Details":
                    {
                        LoggingRepository logrepodetails = new LoggingRepository();
                        TableCell cellEventId = dataItem["EventId"];
                        string strEventId = cellEventId.Text;
                        int eventId = -1;
                        int.TryParse(strEventId, out eventId);
                        if (eventId <= 0)
                            return;
                        details = logrepodetails.GetEventDetails(eventId);
                        e.DetailTableView.DataSource = details;
                        break;
                    }
                case "EntityRow":
                    {
                        List<EntityDto> rowDetails = new List<EntityDto>();
                        string strEntityId = dataItem.GetDataKeyValue("EntityId").ToString();
                        if (e.DetailTableView.ParentItem.OwnerTableView.DataSource == null)
                        {
                            LoggingRepository logrepodetailRows = new LoggingRepository();
                            TableCell cellRowEventId = e.DetailTableView.ParentItem.OwnerTableView.ParentItem["EventId"];
                            string strRowEventId = cellRowEventId.Text;
                            int rowEventId = -1;
                            int.TryParse(strRowEventId, out rowEventId);
                            if (rowEventId <= 0)
                                return;
                            rowDetails = logrepodetailRows.GetEventDetails(rowEventId);

                        }
                        else
                            rowDetails = (List<EntityDto>)e.DetailTableView.ParentItem.OwnerTableView.DataSource;
                        
                        List<EntityRowDto> entityRows = new List<EntityRowDto>();
                        foreach (EntityDto rows in rowDetails)
                        {
                            if (rows.EntityId.ToString() == strEntityId)
                            {
                                foreach (EntityRowDto erdto in rows.EntityRows)
                                    entityRows.Add(erdto);

                                break;
                            }
                            

                        }
                        e.DetailTableView.DataSource = entityRows;
                        break;
                    }

            }
            
        }

0
Accepted
Tsvetoslav
Telerik team
answered on 19 May 2011, 07:15 AM
Hello Jon,

When you are paging a detail table, the parent table view is not rebound and hence its DataSource and the DataItem property of its grid items will be null (instead the data for those is loaded from ViewState) - I suspect this to be the reason for the issue you have encountered. In order to correctly set the data-binding for the detail tables you need to add to the parent table view's DataKeyNames collection any parent item fields you will need for the detail table binding. For example, for the detail table with name "Details" you need to add the EventID field to the DataKeyNames collection of the parent table view. Then in the DetailDataBind event it is very easy to get the value for the field in the parent item: e.DetailTableView.ParentItem.GetDataKeyValye("EventID"). Just do so for each field which value you need to bind the detail tables and pass those values to your data-access layer code.

Hope it helps.

All the best,
Tsvetoslav
the Telerik team

Browse the vast support resources we have to jump start your development with RadControls for ASP.NET AJAX. See how to integrate our AJAX controls seamlessly in SharePoint 2007/2010 visiting our common SharePoint portal.

0
Jon
Top achievements
Rank 1
answered on 19 May 2011, 01:43 PM
Hello Tsvetoslav,

Thanks for correcting me, that information is super. I marked your post as the answer to signal to others that this thread has an answer. It will help those who are searching the forum.


Jon
Tags
Grid
Asked by
Jon
Top achievements
Rank 1
Answers by
Jon
Top achievements
Rank 1
Elliott
Top achievements
Rank 2
Tsvetoslav
Telerik team
Share this question
or