Hi,
I'm hoping that someone here can give me a sample of the usage of EnsureCalculated. I have a UltraGrid with numerous formulas and qute a few custom summaries. The problem I'm having is that the summaries are throwing exceptions because the values that they are meant to summarize have not been calculated in time. Currently, the CalcManager is set to Asynchronous. If I set it to Synchronous everything works fine, so it's obvious what the problem is. I could keep toggling the CalcFrequency property in code but that seems a bit silly.
Infragistics documentation states:
"By default, calculations are done Asynchronously on a timer. This ensures that the UI thread is not locked up when long or complex calculations are performed. The disadvantage to this mode is that a particular value may not be calculated when it is requested in code. When retrieving a calculated value using Asynchronous mode, you should call the EnsureCalculated method to ensure the value has been calculated."
There's very little discussion of EnsureCalculated in the documentation but what there is makes reference to a parameter of type IUltraCalcReference. My question is this: In the AggregateCustomSummary Method of a custom summary (derived from ICustomSummaryCalculator) how can i derive the IUltraCalcReference of the row being passed in as an argument so that I might use EnsureCalculated to make certain that the appropriate cells have been calculated?
any help would certainly be appreciated
Steve
Thanks for your help.
Although using a custom function would not work (yes, we are using a value in another column to determine which rows to include in the summary) I've found that merely intercepting nulls passed to the summaries when they run gives satisfactory performance (at least, for now). No errors are thrown, the yearly summaries (formula) actually take a few more seconds to appear, and then the summaries follow, but the users are willing to accept this.
(BTW, EnsureCalculated() definitely doesn't work within the CustomAggregateSummary method. Might be something your development team would want to look at.)
Again, thanks for your informative support.
Hi Steve,
I'm not sure why EnsureCalculated isn't work for you. I haven't heard of any problems with the method, but on the other hand it's not something a lot of people use. So it could be a bug. If you can reproduce this in a small sample project and post it here, I'd be happy to take a look at it for you.
Regarding using a function... by what criteria do you determine which values to you in your calculation? If you write your own custom function and that function gets called with a grid column as a value, then you will be passed a complete list of all of the values in that column. If you are basing your calculations on some other value in the same row or the index of the row, then you are right, I don't think a custom function will work. But if you are basing it on the value itself (like ignoring 0's, for example), then this should be possible.
Thanks for your rapid and informative reply.
Here's what I've found:
EnsureCalculated doesn't seem to work within a CustomSummaryCalculator. I can get the appropriate reference - thanks to your hint about GetReferenceByContext. But EnsureCalculated always returns false (obviously, i've set wait to true). I've even put it in an infinite while Loop, but it never evaluates to true. Interestingly, if I set the CalcManager to Synchronous everything works fine. I'd be glad to send you a code sample. Probably, I'm doing something wrong (although there's no errors thrown) and I would love to see it work.
In regards to using a formula Summary:
The problem is that I need to be able to specify what rows will be used in the Summaries. The FormulaRowIndexSource Property is really what would matter here, not the calculation (which is a simple sum of specific rows), but the FormulaRowIndexSource basically allows you to specify either all rows or visible rows, and that just won't work.
The situation, simplified, is this. Let's say you have multiple job titles on a project, multiple projects in a dept, multiple depts in a division. You're recording hours worked by each job title on each project on a monthly basis - Jan, Feb, Mar etc, 12 columns. A thirteenth column is added to sum the proceeding 12 - sum(Jan, Feb, Mar...). The reason for the CustomSummaries I'm using is this: We have to summarize hours for each job Title, for each dept, for each division. I can do this easily in a CustomSummaryCalculation by examing each row passed into AggregateCustomSummary method, determining from the value in the job title column if the row is one I'm currently summarizing, (there are ten different job titles), and incrementing the subtotal, etc.
It works fine, but the problem, as originally stated, is that if the CalcManager is set to Asynchronous the CustomSummaryCalculator routine starts before the yearly sum formula above - sum(Jan, Feb, Mar...) is finished, nulls are passed to the CustomSummaryCalculators, and blooey.
Which is why I would dearly love to see EnsureCalculated correctly.
Obviously, the above is simplified. The grid is much more extensive than that - 4 years, not one - more hierarchy, but you get the idea.
By the way, the reason I just don't set the CalcManager to Synchronous and leave it there is that when you do GroupBy's in that mode, it takes, literally, forever.
I'm sorry for the length of this. If you want me to continue this through other channels (code samples, etc.) I'd be glad to.
thanks for any help
What kinds of things does your ICustomSummaryCalculator need? I assume you are referring to cells within a row of the grid?
It's unusual to mix formula summaries with Custom summaries. You might be better off creating a new function and registering it in the CalcManager. That way, your calculations would be done as part of the Calc network, and they would get processed in order. There's a sample included in the NetAdvantage SDK (under the CalcManager samples which demonstrates how to create your own function library and register it with the CalcManager.
If that's no good, then you will need to determine a way to get the IUltraCalcReference that represents the object you need calculated. Assuming this is an UltraGridCell, then I don't think the CalcReference for a cell is exposed in any obvious way. CalcReferences are deliberately hidden because for the most part, you should never have to deal with them directly. But what you can do is use a static method on the grid called GetReferenceFromContext. You can pass in an UltraGridCell and it will return the IUltraCalcReference for that cell.
But you should be aware that EnsureCalculated doesn't go straight to the item you give it. What it essentially does it cause all calculations to be performed synchronously until the reference you gave it is calculated. It doesn't change the order of calculation, either. So it could lock up your UI thread while it's working, which is the same as setting the CalcFrequency to Synchronous. So you are really better off creating your own function and using that, rather than mixing formulas and custom summaries - if you can.