Thank you for your efforts to pinpoint the issue - it's always nice to see someone employing a disassembly tool to see how the things are implemented.
First, I want to apologize for a mistake made in the previous answers: the ReportViewerModel is not
disposable and does not implement IDisposable. It contains resources that need to be disposed (like history records, rendered pages, processed reports, etc.). The confusion probably comes from the fact that there is a method in the ReportViewer incorrectly named DisposeModel()
, which calls the routines for releasing the allocated resources. However, for brevity below I will use "dispose" in sense that the actual model instance will not be disposed, but its resources and event handlers will be disposed.
Now, about the OnUnloaded() and OnWindowClosed() events. They should not perform the same operations, because they serve different scenarios. OnWindowClosed() is the last possible moment when all the events must be detached and resources must be released. OnUnloaded(), on the other hand, will be called when the control is removed from the visual tree but that may not require releasing the model and its resources. For example, when the ReportViewer is hosted in a RadTabControl, switching off the tab will raise the OnUnloaded() event. In this case the tab that contains the ReportViewer should not "dispose" the model, because when the tab is switched on again, the model will reload the report and that's unexpected to the users.. That's why we're only detaching the event handlers but the model is kept alive so when the tab raises OnLoaded() event, the events will be reattached and the report will be displayed without reloading.
Ultimately we do not want to have a window with a "dead" ReportViewer in it. As long as the window is not closed, the ReportViewer must be accessible. Therefore closing the window must call the logic of releasing the resources allocated by the viewer and its model. We're aware that in some scenarios this logic might not fit, that's why we plan to publicly expose the initializing and disposing events, so the developers will have more control on them. In a scenario described earlier in this thread, the user noticed that the Dock.Close does not dispose the report viewer. and that's right - Dock.Close doesn't perform OnWindowClosed() so the viewer is still alive due to the reasons I explained above with the RadTabControl scenario. Having the public disposing methods should resolve this problem.
One particular scenario that requires more attention is when the ReportViewer is hosted in a RadWindow. The RadWindow allows to be closed and then shown again, which cannot be done with the framework's Window control. In this case the ReportViewer "disposes" the model on WindowClosed() but does not instantiate it on Shown() and the application throws an exception. The solution is to instantiate the RadWindow again so the model gets properly initialized.
I hope my post explains why the report viewer is designed this way and which are the expected usage scenarios. Of course, if you need further assistance or some details here were obscure, please do not hesitate to ask.
Do you want to have your say when we set our development plans?
Do you want to know when a feature you care about is added or when a bug fixed?
Telerik Feedback Portal
and vote to affect the priority of the items