Refreshing Child Rows

4 posts, 0 answers
  1. Hannah
    Hannah avatar
    37 posts
    Member since:
    May 2013

    Posted 04 Jun 2014 Link to this post

    I have a grid that displays a parent-child relationship nicely.  The user can select a record and edit it if they choose.  When they do, before the user is returned control of the form, I grab the underlying DataSource, find the record the user just edited, and update it to reflect their changes.  It's faster than refreshing the entire DataSource.

    Like so:

    // select the existing item
    List<Classes.ContractItem> currentContractItems = (List<Classes.ContractItem>)this.dgList.DataSource;
    int index = currentContractItems.FindIndex(c => c.ContractItemId == this.CurrentContractItemId);
     
    if (index != -1)
    {
        currentContractItems.RemoveAt(index);
        currentContractItems.Insert(index, this.CurrentContractItem);
    }
    else
        currentContractItems.Add(this.CurrentContractItem);
     
    this.dgList.DataSource = currentContractItems;

    This works perfectly for the parent.  My problem is refreshing the child rows of the record being updated.  this.CurrentContractItem has a List<T> property that contains all the child records, and they are already updated and ready in the above code.  So there is something additional I need to do to get the grid to refresh it's child rows.

    I've tried several things, reviewed and tried several posts that I found on here.  Most were ancient and needed translation from obsolete methods and properties, but I tried them anyway.

    What can I do to get the child rows to refresh themselves when the underlying DataSource has changed?


    The RadGrid has a Template
  2. Hannah
    Hannah avatar
    37 posts
    Member since:
    May 2013

    Posted 05 Jun 2014 Link to this post

    I want to add that I've tried several approaches.  My current approach seems to me to be the best direction, at least I thought it was until I ran into a brick wall.

    I decided that perhaps the best way to do this was to repopulate the child rows upon the Expanding event, so I'm consuming the ChildViewExpanding event and using the following code:

    void DataGrid_ChildViewExpanding(object sender, ChildViewExpandingEventArgs e)
    {
        if (e.IsExpanded)
        {
            this.dgList.DataGrid.TableElement.BeginUpdate();
            while (e.ParentRow.ViewTemplate.Templates[0].Rows.Count > 0)
                e.ParentRow.ViewTemplate.Templates[0].Rows.RemoveAt(0);
            this.dgList.DataGrid.TableElement.EndUpdate();
        }
        else
        {
            Classes.ContractItem parentRow = (Classes.ContractItem)e.ParentRow.DataBoundItem;
            parentRow.LoadSubItems();
     
            if (parentRow.ContractItemStatuses != null)
                foreach (var i in parentRow.ContractItemStatuses)
                {
                    if (e.ParentRow.ViewTemplate.Templates[0].Columns.Count == 0)
                        e.ParentRow.ViewTemplate.Templates[0] = GetChildTemplate();
     
                    GridViewRowInfo row = e.ParentRow.ViewTemplate.Templates[0].Rows.NewRow();
                    row.Cells["Status"].Value = i.Status;
                    row.Cells["SubjectItem"].Value = i.SubjectItem;
                    row.Cells["SentTo"].Value = i.SentTo;
                    row.Cells["ReceivedFrom"].Value = i.ReceivedFrom;
                    row.Cells["ByUser"].Value = i.ByUser;
                    row.Cells["OnDate"].Value = i.OnDate;
                    row.Cells["Via"].Value = i.Via;
                    row.Cells["Notes"].Value = i.Notes;
                    row.Cells["CreateDate"].Value = i.CreateDate;
                    row.Cells["CreateBy"].Value = i.CreateBy;
     
                    e.ParentRow.ViewTemplate.Templates[0].Rows.Add(row);
                }
     
            e.ParentRow.ViewTemplate.Refresh();
        }
    }

    I've stepped through this and have watched everything populate correctly.  The final line attempting to Refresh() the grid is me flailing about trying different things hoping for a positive result.

    In the end, it always ends the same.  The ChildViewExpanding event completes successfully, then suddenly I'm throwing an "Object reference not set to an instance of an object." error back up on my Application.Run line.  

    Here is the stack trace:

    at Telerik.WinControls.UI.GridTraverser.IsNewRowVisible(GridViewNewRowInfo newRow)
    at Telerik.WinControls.UI.GridViewInfo.HasChildRows()
    at Telerik.WinControls.UI.GridViewHierarchyRowInfo.HasChildRows()
    at Telerik.WinControls.UI.GridTraverser.CanStepInHierarchy()
    at Telerik.WinControls.UI.GridTraverser.StepInHierarchy()
    at Telerik.WinControls.UI.GridTraverser.MoveNextCore()
    at Telerik.WinControls.UI.GridTraverser.MoveNext()
    at Telerik.WinControls.UI.GridTableElement.UpdateOnRowExpandedCore(GridViewRowInfo row)
    at Telerik.WinControls.UI.GridTableElement.UpdateOnRowExpanded(GridViewRowInfo row)
    at Telerik.WinControls.UI.GridTableElement.UpdateOnRowPropertyChanged(GridViewRowInfo row, GridPropertyChangedEventArgs e)
    at Telerik.WinControls.UI.GridTableElement.ProcessRowEvent(GridViewRowInfo row, GridViewEvent eventData)
    at Telerik.WinControls.UI.GridTableElement.Telerik.WinControls.UI.IGridViewEventListener.ProcessEvent(GridViewEvent eventData)
    at Telerik.WinControls.UI.GridViewEventProcessEntity.ProcessCollection(GridViewEvent gridEvent, PriorityWeakReferenceList list, GridEventProcessMode processMode)
    at Telerik.WinControls.UI.GridViewEventProcessEntity.Process(GridViewEvent gridEvent)
    at Telerik.WinControls.UI.GridViewEventProcessEntity.ProcessEvent(GridViewEvent gridEvent)
    at Telerik.WinControls.UI.GridViewSynchronizationService.NotifyListeners(GridViewEvent gridEvent)
    at Telerik.WinControls.UI.GridViewSynchronizationService.FlushEvents()
    at Telerik.WinControls.UI.GridViewSynchronizationService.DispatchEvent(GridViewEvent gridEvent)
    at Telerik.WinControls.UI.GridViewSynchronizationService.DispatchEvent(GridViewTemplate template, GridViewEvent eventData, Boolean postUI)
    at Telerik.WinControls.UI.GridViewRowInfo.DispatchEvent(KnownEvents id, GridEventType type, GridEventDispatchMode dispatchMode, Object originator, Object[] arguments)
    at Telerik.WinControls.UI.GridViewRowInfo.OnPropertyChanged(PropertyChangedEventArgs args)
    at Telerik.WinControls.UI.GridViewDataRowInfo.OnPropertyChanged(PropertyChangedEventArgs e)
    at Telerik.WinControls.UI.GridViewHierarchyRowInfo.OnPropertyChanged(PropertyChangedEventArgs e)
    at Telerik.WinControls.UI.GridViewRowInfo.SetBooleanProperty(String propertyName, Int32 propertyKey, Boolean value)
    at Telerik.WinControls.UI.GridViewRowInfo.set_IsExpanded(Boolean value)
    at Telerik.WinControls.UI.GridGroupExpanderCellElement.expander_RadPropertyChanged(Object sender, RadPropertyChangedEventArgs e)
    at Telerik.WinControls.RadPropertyChangedEventHandler.Invoke(Object sender, RadPropertyChangedEventArgs e)
    at Telerik.WinControls.RadObject.OnPropertyChanged(RadPropertyChangedEventArgs e)
    at Telerik.WinControls.RadElement.OnPropertyChanged(RadPropertyChangedEventArgs e)
    at Telerik.WinControls.VisualElement.OnPropertyChanged(RadPropertyChangedEventArgs e)
    at Telerik.WinControls.RadComponentElement.OnPropertyChanged(RadPropertyChangedEventArgs e)
    at Telerik.WinControls.RadItem.OnPropertyChanged(RadPropertyChangedEventArgs e)
    at Telerik.WinControls.UI.UIItemBase.OnPropertyChanged(RadPropertyChangedEventArgs e)
    at Telerik.WinControls.UI.LightVisualElement.OnPropertyChanged(RadPropertyChangedEventArgs e)
    at Telerik.WinControls.UI.ExpanderItem.OnPropertyChanged(RadPropertyChangedEventArgs e)
    at Telerik.WinControls.RadObject.RaisePropertyNotifications(RadPropertyValue propVal, Object oldValue, Object newValue, ValueSource oldSource)
    at Telerik.WinControls.RadObject.SetValueCore(RadPropertyValue propVal, Object propModifier, Object newValue, ValueSource source)
    at Telerik.WinControls.RadElement.SetValueCore(RadPropertyValue propVal, Object propModifier, Object newValue, ValueSource source)
    at Telerik.WinControls.RadObject.SetValue(RadProperty property, Object value)
    at Telerik.WinControls.UI.ExpanderItem.set_Expanded(Boolean value)
    at Telerik.WinControls.UI.ExpanderItem.ToggleExpanded()
    at Telerik.WinControls.UI.ExpanderItem.OnMouseUp(MouseEventArgs e)
    at Telerik.WinControls.RadElement.OnCLREventsRise(RoutedEventArgs args)
    at Telerik.WinControls.RadElement.OnBubbleEvent(RadElement sender, RoutedEventArgs args)
    at Telerik.WinControls.RadItem.OnBubbleEvent(RadElement sender, RoutedEventArgs args)
    at Telerik.WinControls.RadElement.RaiseBubbleEvent(RadElement sender, RoutedEventArgs args)
    at Telerik.WinControls.RadItem.RaiseBubbleEvent(RadElement sender, RoutedEventArgs args)
    at Telerik.WinControls.RadElement.RaiseRoutedEvent(RadElement sender, RoutedEventArgs args)
    at Telerik.WinControls.RadElement.DoMouseUp(MouseEventArgs e)
    at Telerik.WinControls.RadElement.CallDoMouseUp(MouseEventArgs e)
    at Telerik.WinControls.ComponentInputBehavior.OnMouseUp(MouseEventArgs e)
    at Telerik.WinControls.RadControl.OnMouseUp(MouseEventArgs e)
    at Telerik.WinControls.UI.RadGridView.OnMouseUp(MouseEventArgs e)
    at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
    at System.Windows.Forms.Control.WndProc(Message& m)
    at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
    at Telerik.WinControls.RadControl.WndProc(Message& m)
    at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
    at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
    at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
    at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
    at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
    at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
    at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
    at System.Windows.Forms.Application.Run(Form mainForm)
    at Contracts.Program.Main() in D:\Data\Winapps\Contracts\Program.cs:line 39
    at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
    at System.AppDomain.nExecuteAssembly(RuntimeAssembly assembly, String[] args)
    at System.Runtime.Hosting.ManifestRunner.Run(Boolean checkAptModel)
    at System.Runtime.Hosting.ManifestRunner.ExecuteAsAssembly()
    at System.Runtime.Hosting.ApplicationActivator.CreateInstance(ActivationContext activationContext, String[] activationCustomData)
    at System.Runtime.Hosting.ApplicationActivator.CreateInstance(ActivationContext activationContext)
    at System.Activator.CreateInstance(ActivationContext activationContext)
    at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssemblyDebugInZone()
    at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
    at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
    at System.Threading.ThreadHelper.ThreadStart()

    It seems that something internal to the GridView is causing a problem here, and I'm not sure if it's something I can control or not.

    Ideas?

    I Would love for this to work since it would then help me speed up my grids tremendously.
  3. Hannah
    Hannah avatar
    37 posts
    Member since:
    May 2013

    Posted 05 Jun 2014 in reply to Hannah Link to this post

    Also, I know this will come up.  Yes, this is not a standard implementation of the Grid.  I have wrapped it in a UserControl so that I can place a nice toolbar above the grid to allow the user to toggle filtering, grouping and provide a favorites view mechanism.  

    The data is applied to a dynamic property type and then applied to the grids DataSource property.  The properties that I have not extended are obvious since you will see the DataGrid property as you do in the above this.dgList.DataGrid.TableElement.BeginUpdate() statement.
  4. Dess | Tech Support Engineer, Sr.
    Admin
    Dess | Tech Support Engineer, Sr.  avatar
    3167 posts

    Posted 09 Jun 2014 Link to this post

    Hello Wayne,

    Thank you for writing.

    RadGridView is capable of fetching bindable properties and data. However, one important issue must be noted: During the data binding process, the grid extracts the data from the data source, but for any later changes in the data source, RadGridView should be notified. I have prepared a sample project, demonstrating how to reflect changes coming from the child template's data source. Our Reflecting Custom Object Changes in RGV help article is quite useful about this topic.

    I hope this information helps. Should you have further questions, I would be glad to help.

    Regards,
    Desislava
    Telerik
     
    Check out Telerik Analytics, the service which allows developers to discover app usage patterns, analyze user data, log exceptions, solve problems and profile application performance at run time. Watch the videos and start improving your app based on facts, not hunches.
     
Back to Top