扩展时,Reporting Services会自动滚动到锚点

时间:2009-05-29 20:50:50

标签: internet-explorer reporting-services

当用户通过单击加号展开行组时,Reporting Services似乎认为通过自动滚动网页来“有用”。如果没有黑客入侵Microsoft DLL,有没有人知道如何阻止这种行为?

在网上搜索,我找到了this years-old thread discussing the same issue,但没有回答。我希望我在SO的朋友可能会更加知识渊博。

4 个答案:

答案 0 :(得分:1)

我刚刚遇到同样的问题,并进行了肮脏的修复!我正在使用报表查看器控件在我自己的自定义ASP.Net页面中显示报表。这有助于我,因为我可以在我的外部主页中添加一些额外的脚本。这是我做的:

我在我的页面上打开了MaintainScrollPositionOnPostback因为我很懒,只是劫持了他们的功能来计算滚动条的位置。

我设置一个间隔来每50ms捕获一次滚动条Y位置。

我将一个事件处理程序附加到SSRS IFrame的load事件,它将滚动条设置回原来的位置。

当SSRS回发iframe加载事件时。此时SSRS已经烦恼地调整了滚动条。我的事件处理程序启动并将其放回原位!这很令人作呕,但是做到了。

代码:

<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>

答案 1 :(得分:1)

直接将reportviewer js本地ScrollToTarget函数改为ReportViewerWebForm.aspx:

$(document).ready(function () { 
  Microsoft.Reporting.WebFormsClient._ReportArea.prototype.ScrollToTarget = function(){};
}); 

答案 2 :(得分:0)

如果您知道如何做,那么明确的解决方案非常简单。 ;)

您需要做的就是添加以下代码:

    

<script type="text/javascript" language="javascript">

    $(document).ready(function() {
        $('.A0').get(0).ClientController.CustomOnReportLoaded = function() {
            this.m_reportObject.m_navigationId = null;
        };
    });

</script>

其中来自$('.A0')的“A0”是分配给ReportViewer控件的css类名。

供参考我正在粘贴方法初始化ReportViewer控件:

    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();
    }

在以上示例中调用,如:

    InitializeReportViewer("A0");

以下解释,为何有效:

ReportViewer控件会生成大量的javascript代码,其中包含以下内容:

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();
}

烦人的滚动是因为这部分代码:

    if (null != this.m_navigationId && this.m_navigationId != "")
        window.location.replace("#" + this.m_navigationId);

所以我们需要将this.m_navigationId设置为null。 在哪里?

在调用代码this.m_clientController.OnReportLoaded方法的这一部分之前,最后是方法CustomOnReportLoaded()的调用,所以我们只需要在此方法中为m_navigationId设置null。 我们正在这样做。瞧!

答案 3 :(得分:0)

使用ReportViewer控件10.0.30319.1时为我工作。它不是非常漂亮,因为它触及_ReportArea,它应该是私有的,并且在某些情况下可能需要消除ScrollToTarget函数。另一种方法是通过访问控件来访问ReportPage的此函数和\或NavigationId属性,但是您需要知道确切的控件ID - 在我的例子中它是reportViewerDivId_ctl09,它是根据rsweb的客户端ID构建的: ReportViewer Asp.Net控件。 见第二个例子

示例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 () { };
        } 
    }
});

示例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 */
}