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

GridView within a GridView

9 Answers 68 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Chris Kirkman
Top achievements
Rank 1
Chris Kirkman asked on 22 Jan 2018, 04:47 PM
I imagine there is a way to show another grid view within a selected row of the parent grid view.  This would be something very similar to the row details template within a WPF application.  See attached screenshot from a demo WPF app.

9 Answers, 1 is accepted

Sort by
0
Dimitar
Telerik team
answered on 23 Jan 2018, 08:45 AM
Hi Chris,

This can be achieved by using a hierarchy grid. For example, you can use the Load-On-Demand Hierarchy in order to dynamically pass the details grid data. This way you will not need to relate the templates. In addition, you can hide the expander column and expand the child view when the current row is changed. I have attached a small example that shows how you can implement this.

I hope this will be useful. Let me know if you have additional questions.

Regards,
Dimitar
Progress Telerik
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Chris Kirkman
Top achievements
Rank 1
answered on 23 Jan 2018, 04:44 PM

This works pretty well.  Is there a way I can bind an object to my child grid?  Instead of the following code you gave me...

private void BatchComparisonGrid_RowSourceNeeded(object sender, GridViewRowSourceNeededEventArgs e)
{
    // get item bound to the row
    ComparisonScanViewModel model = e.ParentRow.DataBoundItem as ComparisonScanViewModel;
 
    // build values to go in the row details grid
    GridViewRowInfo row = e.Template.Rows.NewRow();
    row.Cells["Description"].Value = "test param";
    row.Cells["Value"].Value = "20 cm";
    e.SourceCollection.Add(row);
}

 

My "ComparisonScanViewModel" has a BindingList<myobject> as a property that I would prefer to bind to the child grid.

0
Chris Kirkman
Top achievements
Rank 1
answered on 23 Jan 2018, 06:51 PM
Another question...  I'd like to add some level of padding around the child table, perhaps add a label as well indicating the contents of the table.  See attached WPF example versus what I'm getting from RadGridView right now.
0
Chris Kirkman
Top achievements
Rank 1
answered on 23 Jan 2018, 09:14 PM

Hopefully this will be last question on this thread.  :)

I need to show a separate grid via the method above, which works fine; however, the processing time I do in the "RowSourceNeeded" event can be lengthy.  When I use the async...await method the grid never updates.  If I don't use this method the grid updates correctly but can take several seconds depending on how quickly my action can complete.

The lengthy part is the call to the "model.Parameters" property.  Now, if I come back again and select this row in the grid, it DOES show the child grid; however, it won't update the UI unless I do that.  Perhaps you can see something in the source code that can be done differently?

 

private async void BatchComparisonGrid_RowSourceNeeded(object sender, GridViewRowSourceNeededEventArgs e)
{
    // tell user we're getting the analysis parameters
    UpdateWaitingBar(ElementVisibility.Visible, "Getting analysis parameters");
 
    // get item bound to the row
    ComparisonScanViewModel model = e.ParentRow.DataBoundItem as ComparisonScanViewModel;
 
    await Task.Factory.StartNew(() =>
    {
        if (null != model && null != model.Parameters)
        {
            // I don't do anything here, I just needed to cause 'model.Parameters' to
            // be called since it is a timely call.
        }
    });
 
    // update the UI
    if (null != model &&
        null != model.Parameters)
    {
        foreach (ComparisonAnalysisParameterViewModel am in model.Parameters)
        {
            // build values to go in the row details grid
            GridViewRowInfo row = e.Template.Rows.NewRow();
            row.Cells["Description"].Value = am.Title;
            row.Cells["Value"].Value = am.Value;
 
            e.SourceCollection.Add(row);
        }
    }
 
     // tell the user we're done
    UpdateWaitingBar(ElementVisibility.Collapsed);
}
0
Dimitar
Telerik team
answered on 24 Jan 2018, 11:24 AM
Hi Chris,

1. If you want to bind the template you will need to create a hierarchy relation. Detailed information is available here: Binding to Hierarchical Data Programmatically | RadGridView.

2. You can use the ViewCellFormatting event to set the padding and the text:
private void RadGridView1_ViewCellFormatting(object sender, CellFormattingEventArgs e)
{
    GridDetailViewCellElement cell = e.CellElement as GridDetailViewCellElement;
    if (cell != null)
    {
        e.CellElement.Padding = new Padding(10);
        e.CellElement.Text = "Text";
        e.CellElement.TextAlignment = ContentAlignment.TopLeft;
        cell.ChildTableElement.Margin = new Padding(0, 18, 0, 0);
    }
    else
    {
        e.CellElement.ResetValue(LightVisualElement.PaddingProperty, ValueResetFlags.Local);
        e.CellElement.ResetValue(LightVisualElement.TextAlignmentProperty, ValueResetFlags.Local);
         
    }
}

3. You will need the data in the RowSourceNeeded event. What might work is cache the data and get it asynchronously when the form is shown (this should not block the UI). This way it will be ready when needed. 

I hope this will be useful.

Regards,
Dimitar
Progress Telerik
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Chris Kirkman
Top achievements
Rank 1
answered on 24 Jan 2018, 02:27 PM
caching data won't work for me.  I could have 'x' # of rows and each row could take anywhere from milliseconds to several seconds to fetch what will go in the grid via the RowSourceNeeded event.  So, pre-loading when the form is displayed is very expensive.  Plus, the user can select a drop down value in a list on the form and then my values need to be recalculated.  ;(
0
Chris Kirkman
Top achievements
Rank 1
answered on 24 Jan 2018, 02:40 PM
Is there anyway that after I add the child table in the RowSourceNeeded event I can then capture the CellClick event (or some other event that fires when I've clicked on that row) and force the child grid to be displayed?
0
Chris Kirkman
Top achievements
Rank 1
answered on 24 Jan 2018, 03:04 PM
Dimitar, I added "e.ParentRow.IsExpanded = true;" inside RowSourceNeeded right after adding all the new rows to the SourceCollection.  That made it display as soon as I needed it to.
0
Dimitar
Telerik team
answered on 25 Jan 2018, 09:27 AM
Hello Chris,

This can lead to a stack overflow exception because expanding the row will trigger the RowSourceNeeded event. The only way to get the data async I can think of is showing a waiting bar while the async task is working and then refreshing the grid after that. In your case, you need to use the following code to refresh the child template:
this.radGridView1.Templates[0].Refresh();

In addition, I have attached a sample implementation for this (using an async method with a callback).

I hope this will be useful.  

Regards,
Dimitar
Progress Telerik
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
Tags
GridView
Asked by
Chris Kirkman
Top achievements
Rank 1
Answers by
Dimitar
Telerik team
Chris Kirkman
Top achievements
Rank 1
Share this question
or