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

RowSourceNeeded Problem

3 Answers 242 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 25 Jan 2018, 04:03 PM

I have a RowSourceNeeded event, and inside that event I create my child GridView and add rows to it.  There are conditions that would keep me from adding the child GridView; however, I still need to add this child when I do have the data required to do so.

In this event I check a property "model.Parameters" which could be null; however, it is not always going to be null (after handling the RowSourceNeeded event) and when not null I need to add the child GridView.

Here's where I add it.

// get the analysis parameter differences for this row (scan)
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);
        }
 
        e.ParentRow.IsExpanded = true;
    }
 
    // tell the user we're done
    UpdateWaitingBar(ElementVisibility.Collapsed);
}

 

Later, I'm listening to the CurrentRowChanging event.  Here I can get the same data from the model and potentially build the child GridView; however, I don't have the necessary information required that was provided to me in the RowSourceNeeded event.  I.e. e.Template and e.SourceCollection.

 

// row is changing in the grid and time to expand that item to show the details for the row
private void BatchComparisonGrid_CurrentRowChanging(object sender, CurrentRowChangingEventArgs e)
{
    if (e.NewRow is GridViewHierarchyRowInfo)
    {
        foreach (var item in BatchComparisonGrid.Rows)
        {
            item.IsExpanded = false;
        }
 
        // get model
        ComparisonScanViewModel model = e.NewRow.DataBoundItem as ComparisonScanViewModel;
        if(null != model.Parameters)
        {
            // code would go here that checks to see if this row already had the child GridView
            // added, and if not AND model.Parameters is not null, then we'll add the child GridView now.
 
            // BUT, how to do this from here ????
        }
 
        // expand
        e.NewRow.IsExpanded = true;
    }
}

 

Is there some way to access what I need from the CurrentRowChanging event in order to add the child GridView...since the RowSourceNeeded event is never raised again after the first time it is raised?

 

 

3 Answers, 1 is accepted

Sort by
0
Accepted
Dess | Tech Support Engineer, Principal
Telerik team
answered on 26 Jan 2018, 08:48 AM
Hello, Chris,

Thank you for writing.  

When you use the load on demand hierarchy approach in RadGridView, the first time you try expanding a parent node, the RowSourceNeeded event is called. In the event handler you fill the data for the respective template and parent row. This data is cached and the next time you expand the same parent RadGridView uses the cached data. In the CurrentRowChanging event you have access to the new current row from where you can get the template by the CurrentRowChangingEventArgs.NewRow.ViewTemplate property. However, you don't have access to the SourceCollection. It is relevant for the GridViewRowSourceNeededEventArgs. You can store in an external data structure the necessary information from the SourceCollection when the RowSourceNeeded event is fired and use it later when the CurrentRowChanging event is fired. Alternatively, you can extract this information directly from your data source. Feel free to use this approach which suits your requirement best.

I hope this information helps. Should you have further questions I would be glad to help. 
 
 Regards,
Dess
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 26 Jan 2018, 01:59 PM

I tried something similar to what you suggested yesterday and was getting an exception saying that I couldn't access a disposed object.  However, this must have been talking about the GridViewRowSourceNeededEventArgs.  Instead today I decided to only cache the GridViewTemplate and the SourceCollection from those event args for when I do have what I need to fill it in.  I added the following code to be able to handle caching what I need to do this.

List<RowSource> _sources = new List<RowSource>();
class RowSource
{
    public int Id { get; set; }
    public GridViewTemplate Template { get; set; }
    public IList<GridViewRowInfo> SourceCollection
    {
        get; set;
    }
}
void AddChild(RowSource source, ComparisonScanViewModel model)
{
    foreach (ComparisonAnalysisParameterViewModel am in model.Parameters)
    {
        // build values to go in the row details grid
        GridViewRowInfo row = source.Template.Rows.NewRow();
        row.Cells["Description"].Value = am.Title;
        row.Cells["Value"].Value = am.Value;
 
        source.SourceCollection.Add(row);
    }
 
    //source.ParentRow.IsExpanded = true;
}

 

Now, I changed the RowSourceNeeded to include the following...

else
{
    // cache until I can actually load with model data
    _sources.Add(new RowSource()
    {
        Id = model.Id,
        Template = e.Template,
        SourceCollection = e.SourceCollection,
    });
}

 

Then, I changed the CurrentRowChanging to check to see if I have what I need to place the data in to the SourceCollection as shown below.

// get model
ComparisonScanViewModel model = e.NewRow.DataBoundItem as ComparisonScanViewModel;
if (null != model.Parameters)
{
    // was the row source not able to be set before because the parameters
    // were not available at the time?  check again now and if it IS
    // available we have the ability to add the child gridview now.
    RowSource source = _sources.Find(s => s.Id == model.Id);
    if (null != source)
    {
        AddChild(source, model);
        _sources.Remove(source);
    }
}

 

It appears to be working now, so that's good.  Thanks.

0
Dess | Tech Support Engineer, Principal
Telerik team
answered on 29 Jan 2018, 12:39 PM
Hello, Chris,  

Thank you for writing back. 

I am glad that the provided information was useful for handling your scenario. The provided code snippet seems OK. Hence, if it behavse the way you need, feel free to use it.

I hope this information helps. If you have any additional questions, please let me know. 

 Regards,
Dess
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
Dess | Tech Support Engineer, Principal
Telerik team
Chris Kirkman
Top achievements
Rank 1
Share this question
or