We are getting an error that is hard to duplicate and occurs at different points. The common occurrences seem to be when our grid is filtered and the user double clicks on a record to do some editing. When they come back from the editing dialog and we try to refresh the grid, this error occurs and the message "Object reference not set to an instance of an object" pops up.
When we run it in debug mode, it does not error out on any specific line of code, so we are having problems figuring out where the error is happening and on what code. From the detail below, its is happening on some type of calculations, but we have no idea how to figure out what its doing at the time or on what calculation. Any ideas? We are using Infragistics 8.3 still
thanks!
See the end of this message for details on invoking just-in-time (JIT) debugging instead of this dialog box.************** Exception Text **************System.NullReferenceException: Object reference not set to an instance of an object. at Infragistics.Win.UltraWinGrid.RefUtils.GetRowCalcIndex(UltraGridRow row, FormulaRowIndexSource rowIndexType) at Infragistics.Win.UltraWinGrid.RefRowIterator.GetNextRow() at Infragistics.Win.UltraWinGrid.RefRowIterator.MoveNext() at Infragistics.Win.UltraWinGrid.RefRowIterator.MoveNext() at Infragistics.Win.UltraWinGrid.RefRowIterator.MoveNext() at Infragistics.Win.UltraWinGrid.RefCellCollection.RefCellCollectionEnumerator.MoveNext() at Infragistics.Win.CalcEngine.RangeCalcInfo.EvaluateNextRow() at Infragistics.Win.CalcEngine.UltraCalcEngine.Evaluate(Int64 ticks) at Infragistics.Win.CalcEngine.UltraCalcEngine.Recalc(Int64 ticks, Boolean isStartOfRecalcOperation) at Infragistics.Win.UltraWinCalcManager.UltraCalcManager.ReCalcInternal(Int64 ticks) at Infragistics.Win.UltraWinCalcManager.UltraCalcManager.ReCalc(Int64 millis) at Infragistics.Win.UltraWinCalcManager.UltraCalcManager.ReCalc() at Infragistics.Win.UltraWinCalcManager.UltraCalcManager.ReCalcSynchronous() at Infragistics.Win.UltraWinCalcManager.UltraCalcManager.VerifyReCalc() at Infragistics.Win.UltraWinCalcManager.UltraCalcManager.DirtyCalc(IUltraCalcReference reference, ValueDirtiedAction action) at Infragistics.Win.UltraWinCalcManager.UltraCalcManager.Infragistics.Win.CalcEngine.IUltraCalcManager.RowsCollectionVisibilityChanged(IUltraCalcReference reference) at Infragistics.Win.UltraWinGrid.ViewStyleBase.OnAfterRowListCreated_ProcessBand(UltraGridBand band) at Infragistics.Win.UltraWinGrid.ViewStyleBase.OnAfterRowListCreated(RowScrollRegion rsr) at Infragistics.Win.UltraWinGrid.ViewStyleBase.RecreateRowList(RowScrollRegion rsr) at Infragistics.Win.UltraWinGrid.RowScrollRegion.RegenerateVisibleRows(Boolean resetScrollInfo) at Infragistics.Win.UltraWinGrid.RowScrollRegion.WillScrollbarBeShown(ScrollbarVisibility assumeColScrollbarsVisible) at Infragistics.Win.UltraWinGrid.RowScrollRegion.PositionScrollbar(Boolean resetScrollInfo) at Infragistics.Win.UltraWinGrid.ScrollRegionBase.SetOriginAndExtent(Int32 origin, Int32 extent) at Infragistics.Win.UltraWinGrid.RowScrollRegion.SetOriginAndExtent(Int32 origin, Int32 extent) at Infragistics.Win.UltraWinGrid.DataAreaUIElement.ResizeRowScrollRegions() at Infragistics.Win.UltraWinGrid.DataAreaUIElement.PositionChildElements() at Infragistics.Win.UIElement.VerifyChildElements(ControlUIElementBase controlElement, Boolean recursive) at Infragistics.Win.UltraWinGrid.DataAreaUIElement.VerifyChildElements(ControlUIElementBase controlElement, Boolean recursive) at Infragistics.Win.UltraWinGrid.DataAreaUIElement.set_Rect(Rectangle value) at Infragistics.Win.UltraWinGrid.UltraGridUIElement.PositionChildElements() at Infragistics.Win.UIElement.VerifyChildElements(ControlUIElementBase controlElement, Boolean recursive) at Infragistics.Win.UltraWinGrid.UltraGridUIElement.VerifyChildElements(ControlUIElementBase controlElement, Boolean recursive) at Infragistics.Win.UIElement.VerifyChildElements(Boolean recursive) at Infragistics.Win.ControlUIElementBase.VerifyIfElementsChanged(Boolean verify, Boolean syncMouseEntered) at Infragistics.Win.ControlUIElementBase.ProcessMouseMoveHelper(Object sender, MouseEventArgs e) at Infragistics.Win.ControlUIElementBase.ProcessMouseMove(Object sender, MouseEventArgs e) at Infragistics.Win.Utilities.ProcessEvent(Control control, ProcessEvent eventToProcess, EventArgs e) at Infragistics.Win.UltraControlBase.OnMouseMove(MouseEventArgs e) at System.Windows.Forms.Control.WmMouseMove(Message& m) at System.Windows.Forms.Control.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.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
Hi,
From the call stack, it looks like the error is occurring on a MouseMove. So the mouse must be moving over a cell in the grid which causes the grid to try to verify it's display and this causes the grid to rebuild it's list of rows which was dirtied at some prior point.
The fact that the grid is blowing up while trying to create the rows is in indication that something is out of synch, which leads me to think that this might be a threading issue.
So what exactly are you doing when you "try to refresh the grid". Is your code using threads anywhere?
Hi Mike,
I had a very similar exception seen today. The only difference being that a summary value was being calculated as shown in the RefSummaryValueCollection in the stack trace. I have to admit that I have seen calculator bugs when using filtering since version 7.2 and have never updated the binding list on the grids except from the GUI thread. Their are five bands in the grid and there is a summary for band 2 that has a formula that references a value in the parent row and the sum of a column in the band 2 rows. There is also a summary for band 0 that is just a simple sum of each column.
I add, remove, or update the binding list periodically by doing an Invoke on the GUI thread and have seen calculator bugs (rarely however). I have removed the calculator as much as possible having even resorted to setting Row.Hidden to true instead of using a filter in previous projects but not this one. I am using version 8.2.20082.2204. The CalcFrequency is set to synchronous. I believe part of the problem is the fact that setting a filter is not a synchronous operation in the Grid so sometimes I have resorted to using EnsureSortedAndFiltered which is synchronous. This exception happened to one of our users so I cannot be exactly sure what they were doing when the exception occurred although as you mentioned above it look like a simple cell activation. Any help or suggestions you can give me would be appreciated. I am wondering at this point if I should resort to always using manual calculations to reduce the chance of an exception like this occuring again. However, I would prefer the bug to be simply fixed as opposed to have to jump through hoops to avoid it.
Here is the call stack:
Thanks, I was able to register the key and download the source for the current service release 8.2.2204 however the pdbs are missing which means I cannot debug the infragistics code which causes the nullreferenceexception when recalculating the summary values. I saw another forum thread here http://blogs.infragistics.com/forums/p/10771/144474.aspx which stated that the pdbs should have been in the source zip file however this is not true. There are no pdbs in the current service release for 2204 for 8.2 for winforms and according to that thread mentioned above they should have been there. Where can I find the pdbs for the current release version 2204 for 8.2 winforms?
I have finally had time to look at these bugs. I will post my preliminary findings now. I want to say the inavailability of .pdb files was a major issue preventing me from making any progress in these issues. I believe this has been a bug in the ultracalc formula calculator since at least 7.1 and it looks like the last changes to the calculator code was back in 2004 from the source so it probably still exists today. My preliminary findings lead to the understanding that the issue surrounds the calculation of formulas where the parent row is filtered out.
My grid is bound to a hierarchical binding list. There are filters on each band of the grid. The calcmanager is set to Synchronous. My FormulaRowIndexSource is set to Visible since I do not want to include filtered out rows in any calculated summation.
What happens is that if I add a business object to the child binding list of a parent business object whose Row has been filtered out then I may get this exception: "Invalid scope in the reference: consolidatedbrokers(-1)." This happens because the AbsoluteName of a CellReference used to calculate a summation that includes the newly added row is: //grid/legalentity(-1)/consolidatedbrokers(-1)/cashbalance. That would be a reference to a cell for the formula "sum( [../brokers/cashbalance] )" in the parent row which is currently filtered out. legalentity being the name of the first band, consolidatedbrokers the second, and brokers the third. There is also a formula on the first band of "sum( [../consolidatedbrokers/cashbalance] )" and there is a summary value for the first band which is "sum( [cashbalance] )".
The source code showing what causes the bug is all from 8.2.20082.2204.
Infragistics.Win.UltraWinGrid.RowReference.ElementName property will return the band name with row index -1 if the row is not visible and the row has never been visible which can happen if the parent row is filtered out. lastValidIndex will be -1 and GetRowCalcIndex returns -1 because the row is not visible (filtered out). This in itself is not a bug but just showing how the AbsoluteName path is formed when a parent row is filtered out.
public override string ElementName { get { int rowCalcIndex = RefUtils.GetRowCalcIndex(base.Row); if ((rowCalcIndex < 0) && (base.lastValidIndex >= 0)) rowCalcIndex = base.lastValidIndex; base.lastValidIndex = rowCalcIndex; string calcReferenceName = base.Row.Band.CalcReferenceName; StringBuilder builder = new StringBuilder(calcReferenceName.Length + 8); builder.Append(calcReferenceName).Append('(').Append(rowCalcIndex).Append(')'); return builder.ToString(); } }
The AbsoluteName property of the CellReference for consolidatebroker band column "cashbalance" is AbsoluteName of "//grid/legalentity(-1)/consolidatedbrokers(-1)/cashbalance". That column has formula "sum( [../brokers/cashbalance] )". Now when a child broker object is added to the binding list the grid performs a synchronous calculation for the newly added row for that business object and the parent rows. To evaluate the formula for cashbalance for the parent row the following method is used from class Infragistics.Win.CalcEngine.UltraCalcFunctionSum:
protected override UltraCalcValue Evaluate(UltraCalcNumberStack numberStack, int argumentCount){ double num = 0.0; foreach (UltraCalcValue value2 in base.GetArguments(numberStack, argumentCount, true)) { if (value2 != null) { double num2; if (value2.IsError) { return new UltraCalcValue(value2.ToErrorValue()); } if (value2.ToDouble(out num2)) { num += num2; } } } return new UltraCalcValue(num);}
The Infragistics.Win.CalcEngine.UltraCalcFunction.GetArguments method called above will iterate the arguments used in the formula. The GetArguments method from UltraCalcFunction is here:
protected UltraCalcValue[] GetArguments(UltraCalcNumberStack numberStack, int argumentCount, bool skipEmptyValues) { ArrayList list = new ArrayList(); for (int i = 0; i < argumentCount; i++) { this.GetArguments(list, numberStack.Pop(), skipEmptyValues); } return (UltraCalcValue[]) list.ToArray(typeof(UltraCalcValue)); }
Which calls this overloaded GetArguments method in the same class:
private void GetArguments(ArrayList list, UltraCalcValue val, bool skipEmptyValues) { if (val.IsReference) { IUltraCalcReference reference = val.ToReference(); if (!reference.IsEnumerable) { this.GetArguments(list, reference.Value, skipEmptyValues); } else { foreach (IUltraCalcReference reference2 in reference.References) { this.GetArguments(list, reference2.Value, skipEmptyValues); } } } else if (!skipEmptyValues || !val.IsNull) { list.Add(val); } }
Now reference.IsEnumerable is true above since it is enumerating the cashbalance for the broker child rows of the consolidatedbroker row which is filtered out. Keep in mind that the skipEmptyValues parameter is false since the FormulaRowIndexSource is Visible. The reference variable above refers to an instance of a Infragistics.Win.UltraWinGrid.NestedColumnReference object whose AbsoluteName is: "//grid/legalentity(-1)/consolidatedbrokers(-1)/brokers/cashbalance".
The References property of the NestedColumnReference object (reference) creates a RefCellCollection using the NestedColumnReference.ParsedReference property as an argument.
public override IUltraCalcReferenceCollection References { get { return this.ScopedReferences(this.ParsedReference); } }
public override IUltraCalcReferenceCollection ScopedReferences(RefParser scopeRP) { return new RefCellCollection(this, this.Column, scopeRP); }
The ParsedReference property creates a RefParser object that is a collection of tuples used to locate the cashbalance cells. The RefParser object for this NestedColumnReference uses the absolute name above to create the reference.
protected virtual RefParser CreateParsedReference() { return new RefParser(this.AbsoluteName); }
The RefParser constructor calls ParseReferences with the AbsoluteName as the argument. ParseReferences parses the name and constructs list RefTuple objects for the name.
Because the AbsoluteName refers to index (-1), for parent rows, the RefParser generates a RefTuple with RefScope of RelativeIndex because the index has a '-' character in it. Remember the -1 index is in the name because the row is not visible, NOT because the relative path to the row is -1 from the current row.
Now the GetEnumerator method of the RefCellCollection returns a RefCellCollectionEnumerator in this line of UltraCalcFunctionSum.Evaluate whose code is shown above.
foreach (IUltraCalcReference reference2 in reference.References)
The MoveNext() method of RefCellCollection calls the MoveNext() method of the rowIterator data member as shown here:
public bool MoveNext() { if (!this.rowIterator.MoveNext()) { return false; } this.cell = this.rowIterator.Current.Cells[this.collection.column]; return (null != this.cell); }
Almost done. Drum roll please :). The MoveNext() method of the RefRowIterator can only iterate rows using the RefTuples created earlier for the following RefScopes: Any, All, Index, Identifier. The code is not shown as it is very long and I'm sure you can find it. The recalcDeferredIterator data member is false so it falls into a switch statement with the RefScope of the RefTuple as the switch argument. The 'default' case is taken for legalentity(-1) tuple since the scope is RelativeIndex and an exception is thrown since this is invalid scope.
So the bug in the calculator can be summed up as the following. When adding a child row to a filtered out parent row that has a column that refers to a child cell value or values, the calculator attempts to evaluate the child cells using an incorrect path. Since the FormulaRowIndexSource was visible one could argue why should it try to calculate the formula at all however I think it is correct to calculate the formula since that formula could be used in a filter on the currently filtered out row however, the logic used to find the cell to include in the formula is wrong. Since the parent row is filtered out, the child row is also hidden so the cells from that child row would normally not contribute to any parent formula however the implementation does not take this into consideration and generates an exception. There is another issue here to take into consideration, that a filter on the parent row might actually use the formula on a column to determine whether the row should be visible or not and never calculating formulas on filtered out rows could cause an issue.
Here's an example. Suppose a parent row has a column foobar with formula "sum( [..child/column] )" and a filter for that band might be something like foobar > 0. Adding a child row to the parent which may currently not be visible should probably still cause the sum column to be evaluated so that the filter can be evaluated properly. However, it looks like the calculator may have a problem doing this.
Forgot to mention if there is any workaround for this bug that you can think of. Only thing I can think of trying is to use a custom formula instead of sum.
Now that I have figured out this bug I think this may very well be the bug that has been plaguing me for years with the calculator in conjunction with filters. It was so bad that I resorted to having to set Hidden on a row instead of using a filter because I would often get the NullReferenceException from the calculator.
I believe the calculator was trying to iterate rows for a formula and would call GetRowCalcIndex with null for the row if a filter was applied to a column and filtered out a parent row.
I look forward to you fixing this bug.
Thanks for opening the case to resolve this if it was you. The developer was unable to reproduce it so I modified the Samples\WinCalcManager\CS\WinGrid Summaries CS project.
Frankly I am astonished that this bug has been in infragistics for so long since its a very basic operation that creates the exception. The bug can be summarized as follows: If a row is added to the grid for band 0, and a child band of that new row has summary values, and the filter on band 0 would cause the new row to be filtered out, then the exception occurs.
Here's a screenshot of the application.
Notice the filter icon on the Id column of band 1 and the summary values on band 2. There is a filter on band 0 that checks if any child rows are not Filtered Out. It just loops over the row collection of any child bands and checks the IsFilteredOut. Here's the linq expression that is evaluated in the filter:
row.ChildBands.Cast<
>()).Any(r => !r.Hidden && !r.IsFilteredOut)
So if the filter on band 1 is changed to equal number 5 for example. If a business object for band 0 is created with a single Part object in its Parts binding list and the Id is not 5, and then the business object is added to the binding list that the data source is bound to then the UltraCalcException will be thrown. This is because the CalcEngine cannot create a reference for the cells used in the summary for band 2 since the parent band 0 row is not visible. The exception is invalid scope: band0name(-1)
emarkunger said:The developer was unable to reproduce it
What developer are you referring to?
Can you post your modified sample so we can try it out? I tried running the WinGrid Summaries CS project, but it doesn't even have a child band in the grid.
As for a workaround, try this:
this.ultraGrid1.DisplayLayout.Override.FormulaRowIndexSource = Infragistics.Win.UltraWinGrid.FormulaRowIndexSource.RowIndex;
Hello Sean K,
Thank you for contacting Infragistics Community.
I have tested the fix for the original issue in 2012 vol2 and everything works ok for me. Since you have a slightly different scenario, the MessageBox might have something to do with that behavior. Could you please comment the code that shows that MessageBox and verify if the same exception going to appear again, just for testing purposes?
Also if you are able to duplicate it in a small sample I will be glad to look into it.
Please feel free to let us know if you have any other questions with this matter.
Note that I able to get rid of this error by setting CalcFrequency on my UltraCalcManager to Synchronous...
I'd like to switch it back to asynch since there's a strong chance I'll be taking a performance hit when this grid loads more than a few rows.
User updates column in grid
AfterCellUpdate is fired/caught
Update is passed to database
------ABOVE ERROR------
MessageBox shows stating that save was successful (Note that all updates are properly being passed to DB)
---APP CRASHES-----------
Note:
No multithreading in this app
Summaries exist (but not on the "TradeExecution" band)
Hi, I'm still getting this error in V 12.2....
at Infragistics.Win.UltraWinGrid.RefRowIterator.MoveNext() at Infragistics.Win.UltraWinGrid.RefSummaryValueCollection.RefSummaryValueCollectionEnumerator.MoveNext() at Infragistics.Win.CalcEngine.RangeCalcInfo.EvaluateNextRow() at Infragistics.Win.CalcEngine.UltraCalcEngine.Evaluate(Int64 ticks) at Infragistics.Win.CalcEngine.UltraCalcEngine.Recalc(Int64 ticks, Boolean isStartOfRecalcOperation) at Infragistics.Win.CalcEngine.UltraCalcEngine.Recalc(Int64 ticks) at Infragistics.Win.UltraWinCalcManager.UltraCalcManager.ReCalcInternal(Int64 ticks) at Infragistics.Win.UltraWinCalcManager.UltraCalcManager.ReCalc(Int64 millis) at Infragistics.Win.UltraWinCalcManager.UltraCalcManager.onTimerTick(Object sender, EventArgs e) at System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m) at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) at System.Windows.Forms.SafeNativeMethods.MessageBox(HandleRef hWnd, String text, String caption, Int32 type) at System.Windows.Forms.MessageBox.ShowCore(IWin32Window owner, String text, String caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, MessageBoxOptions options, Boolean showHelp) at System.Windows.Forms.MessageBox.Show(String text) at FMSClient.SubMenu.TradeEdit.dgEditTrades_AfterCellUpdate(Object sender, CellEventArgs e) in C:\Development\MSMQ\FMSClient\SubMenu\TradeEdit.cs:line 326
Any suggestions?
Hello Srikanth,
This has been already fixed and you could use the latest service release for NetAdvantage for Windows Forms 11.2 - 2074.
This service release is now available under your account at the Infragistics Website. To download the service release, log in to‘My IG’ and select ‘Keys & Downloads’. Select the appropriate tab for this product, then the license key. The available service releases should now be listed on the page.
Please let me know if I can provide any further assistance.