Reputation: 309
Reporting Services appears to believe it is being "helpful" by auto-scrolling the web page whenever a user expands a row group by clicking the plus sign. Short of hacking a Microsoft DLL, does anyone know a way to stop this behavior?
Searching around the net, I've found this years-old thread discussing the same issue, but no answer. I was hoping my friends at SO might be a little more knowledgeable.
Upvotes: 0
Views: 3938
Reputation: 11
Just overright the reportviewer js native ScrollToTarget function into ReportViewerWebForm.aspx:
$(document).ready(function () {
Microsoft.Reporting.WebFormsClient._ReportArea.prototype.ScrollToTarget = function(){};
});
Upvotes: 1
Reputation: 12813
Worked for me when using with ReportViewer control 10.0.30319.1. Not very pretty as it touches the _ReportArea which is supposed to be private and eliminates ScrollToTarget function at all which may be needed in some scenarios. Alternative way is to access this function and \ or NavigationId property of the ReportPage via getting access to controls, but you need to know exact control id - in my case it is reportViewerDivId_ctl09, which is built from the client-side ID of the rsweb:ReportViewer Asp.Net control. See second example
Example 1:
$(window).load(function () {
if (Microsoft && Microsoft.Reporting && Microsoft.Reporting.WebFormsClient) {
var rpp = Microsoft.Reporting.WebFormsClient._ReportArea;
if (rpp && rpp.prototype) {
rpp.prototype.ScrollToTarget = function () { };
}
}
});
Example 2:
/* DOESN'T WORK!*/
var rp = $get('reportViewerDivId_ctl09_ReportControl'); /* rp.control is ReportPage */
rp[0].control.NavigationId = null;
/*THE BELOW WORKED*/
var ra = $('#reportViewerDivId_ctl09'); /*ra[0].control is ReportArea*/
if (ra[0] && ra[0].control && ra[0].control.ScrollToTarget) {
ra[0].control.ScrollToTarget = function () { }; /*overriding the function so that anoying scroll on Sort doesn't happen */
}
Upvotes: 0
Reputation: 151
I've just hit the same issue and put a dirty fix in place! I'm showing reports in my own custom ASP.Net page using the report viewer control. That helps me because I can put some additional script in my outer host page. Here's what I did:
I switched on MaintainScrollPositionOnPostback
on my page as I'm lazy and just hijack their function to work out the scroll-bars y position.
I set an interval to capture the scroll-bars Y location every 50ms.
I attach an event handler to the load event of the SSRS IFrame which will set the scroll bar back to where it previously was.
When SSRS posts back the iframe load event occurs. At this point SSRS has annoyingly adjusted the scroll bar. My event handler kicks in and puts it back! It's pretty disgusting but does the job.
Code:
<script language="javascript">
$(document).ready(function() {
$('iframe').load(function() {
resetScrollbar();
});
});
var lastGoodScrollY = 0;
var interval = window.setInterval(getScrollY, 50);
function getScrollY() {
lastGoodScrollY = WebForm_GetScrollY();
}
function resetScrollbar() {
window.scrollTo(0, lastGoodScrollY);
}
</script>
Upvotes: 1
Reputation: 2803
The clear solution is quite simple, if you know how to do it. ;)
All what you have to do is adding following code:
<script type="text/javascript" language="javascript">
$(document).ready(function() {
$('.A0').get(0).ClientController.CustomOnReportLoaded = function() {
this.m_reportObject.m_navigationId = null;
};
});
</script>
where "A0" from $('.A0')
is css class name assigned to ReportViewer control.
For reference I'm pasting method initializing ReportViewer control:
protected void InitializeReportViewer(string ID)
{
string reportsPath = ConfigGetter.GetReportsPath();
string reportingServerUrl = ConfigGetter.GetReportingServerUrl();
Instance = new ReportViewer();
Instance.ID = ID;
Instance.CssClass += ID;
Instance.ProcessingMode = ProcessingMode.Remote;
Instance.ServerReport.ReportServerUrl = new Uri(reportingServerUrl);
Instance.ServerReport.ReportPath = reportsPath + Config.Filename;
Instance.Enabled = true;
Instance.InternalBorderStyle = BorderStyle.None;
Instance.EnableViewState = true;
if (Config.AutomaticSize)
{
Instance.AsyncRendering = false;
Instance.SizeToReportContent = true;
}
else
{
Instance.Width = Config.Width;
Instance.Height = Config.Height;
}
Instance.ShowParameterPrompts = false;
Instance.ShowToolBar = false;
SetParameters();
}
which is invoked for above example like:
InitializeReportViewer("A0");
Below explanation, why it works:
ReportViewer control generates a lot of javascript code, which contains between others following:
function OnLoadReport(reloadDocMap)
{
this.m_clientController.OnReportLoaded(this, reloadDocMap);
if (null != this.m_navigationId && this.m_navigationId != "")
window.location.replace("#" + this.m_navigationId);
if (this.m_autoRefreshAction != null)
setTimeout(this.m_autoRefreshAction, this.m_autoRefreshInterval);
}
RSReport.prototype.OnLoadReport = OnLoadReport;
function OnReportLoaded(reportObject, reloadDocMap)
{
this.m_reportObject = reportObject;
this.CurrentPage = reportObject.m_pageNumber;
this.TotalPages = reportObject.m_totalPages;
this.m_searchStartPage = reportObject.m_searchStartPage;
// Update the client side page number so that it is available to the server object
// if it was changed asynchronously.
var clientCurrentPage = GetControl(this.m_clientCurrentPageID);
if (clientCurrentPage != null)
clientCurrentPage.value = this.CurrentPage;
// If there is a document map, display it
if (this.HasDocumentMap())
{
// This method is called each time the report loads. This happens
// for page navigations and report actions. For many of these cases,
// the doc map didn't change, so don't reload it.
if (reloadDocMap)
{
if (this.CanDisplayBuiltInDocMap() && this.m_docMapUrl != "")
{
var docMapReportFrame = frames[this.m_docMapReportFrameID];
docMapReportFrame.frames["docmap"].location.replace(this.m_docMapUrl);
}
this.CustomOnReloadDocMap();
}
if (this.m_docMapVisible && this.CanDisplayBuiltInDocMap())
this.SetDocMapVisibility(true);
}
this.CustomOnReportLoaded();
}
Annoying scrolling is because of this part of code:
if (null != this.m_navigationId && this.m_navigationId != "")
window.location.replace("#" + this.m_navigationId);
So we need to set this.m_navigationId
to null.
Where?
Before this part of code this.m_clientController.OnReportLoaded
method is invoked, and on it's end is invokation of method CustomOnReportLoaded()
, so we just need to set null for m_navigationId
in this method.
And we are doing it. Voila!
Upvotes: 0