无法在ReportViewer aspx.net中显示数据表 [英] Can't Display DataTable in ReportViewer aspx.net

查看:65
本文介绍了无法在ReportViewer aspx.net中显示数据表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在ReportViewer控件中显示DataTable对象的内容时遇到困难.没有错误,页面上仅显示一个空白的报表查看器.我已经查看了在这里找到的各种类似问题中提出的解决方案,此处此处-最后一个特别令人沮丧正如最后一条评论所说:让我们继续聊天中的讨论",没有提供任何答案,这本质上是我的确切问题.

I am having difficulty displaying the contents of a DataTable object in a ReportViewer control. There are no errors, just a blank report viewer being shown on the page. I have looked at the solutions presented in various similar questions found here, here and here - that last one is particularly frustrating as the last comment says "let's continue this discussion in chat" with no answer provided and it is essentially my exact issue.

页面代码:

    <div class="panel-body">
         <rsweb:ReportViewer ID="ReportViewer1" runat="server" Width="100%">
              <LocalReport ReportPath="reports\Report1.rdlc">
              </LocalReport>
         </rsweb:ReportViewer>
   </div>

隐藏代码:

protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            string repstr = Request.Form["repId"];
            int repId = -1;
            int.TryParse(repstr, out repId);
            CustomReport rpt = new CustomReport(repId);
            data = rpt.ReportResult.Copy();//The report result property is a DataTable object that can have varying # of columns
            data.TableName = "CustomReport";
            ReportViewer1.ProcessingMode = ProcessingMode.Local;
            ReportDataSource source = new ReportDataSource("CustomReport", data);
            ReportViewer1.LocalReport.DataSources.Clear();
            ReportViewer1.LocalReport.DataSources.Add(source);
            ReportViewer1.DataBind();
            ReportViewer1.LocalReport.Refresh();
            ReportViewer1.Visible = true;
        }
    }

我已经验证了DataTable正在填充数据,并且通过调试,我已经验证了ReportViewer数据属性似乎也具有数据-只是不显示....

I have verified that the DataTable is being populated with data and through debugging I've verified that the ReportViewer data properties appear to have the data as well - it's just not being displayed....

任何帮助将不胜感激!

推荐答案

因此,在经过大量研究和谷歌搜索以及我很棒的开发同事的帮助之后,我遇到了一个解决方案,该解决方案实际上涉及到必须重建.rdlc的xml结构.文件以支持动态列.此方法有两个警告.1.您必须手动配置引用数据源的xml,以指向提供数据表的对象方法,因为报表设计器不支持此方法.我在下面包含了我的xml更改.2.您必须将表添加到报表定义中,该表仅包含一列和一行.也许有人可以做得更好.

So after a lot of research and googling and help from my awesome development colleagues I came across a solution that essentially involves having to reconstruct the xml structure of the .rdlc file in order to support dynamic columns. There are a couple of caveats to this approach. 1. You have to manually configure the xml referencing the datasource to point at your object method that provides the datatable as the report designer does not support this. I've included my xml changes below. 2. You have to add a table to the report definition with only one column and one row. Maybe somebody can do this better.

所以解决方案.首先是rdlc xml数据源配置:

So the solution. First the rdlc xml datasource config:

<DataSet Name="DataSet1">
  <Query>
    <DataSourceName>DataLayer</DataSourceName>
    <!--//Put the table name of your datatable object here-->
    <CommandText>CustomReportsDs</CommandText>
  </Query>
  <!--//This is a single empty field for mapping to the table control-->
  <Fields>
    <Field Name="ReportTitle">
      <DataField>ReportTitle</DataField>
      <rd:TypeName>System.String</rd:TypeName>
    </Field>
  </Fields>
  <rd:DataSetInfo>
    <!--//This must be configured to point to the method that supplies the datatable
        //In my instance the DataSetName is the namespace of the object, 
        //TableName is the object that provides the method and
        //ObjectDataSourceSelectMethod is the method that provides the datatable-->        
    <rd:DataSetName>DataLayer</rd:DataSetName>
    <rd:TableName>CustomReport</rd:TableName>
    <rd:ObjectDataSourceSelectMethod>ReportResult</rd:ObjectDataSourceSelectMethod>
    <rd:ObjectDataSourceType>DataLayer.CustomReport, DataLayer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null</rd:ObjectDataSourceType>
  </rd:DataSetInfo>
</DataSet>

接下来,您必须配置报告查看器以从内存流中接收报告定义:

Next you have to configure the report viewer to recieve the report definition from a memory stream:

            //load the data
            int repId = -1;
            int.TryParse(Request.Form["repId"], out repId);
            CustomReport rpt = new CustomReport(repId);
            DataTable data = rpt.ReportResult.Copy();//The report result property is a DataTable object that can have varying # of columns
            data.TableName = "CustomReportDs";
            //setup the report viewer
            ReportViewer1.ProcessingMode = ProcessingMode.Local;
            ReportViewer1.LocalReport.ReportPath = string.Empty;
            //prepare to load the report definition xml file
            string ReportPath = Server.MapPath(@"\reports\Report1.rdlc");
            //my datatable comes with "friendly" column headings - these don't work well as the xml requires cls compliant
            //columnheadings so here we rename the columns in the data table but preserve the friendly names for use later
            Dictionary<string, string> columns = new Dictionary<string, string>();
            int counter = 0;
            foreach(DataColumn col in data.Columns)
            {
                columns.Add("column"+counter.ToString(), col.ColumnName);
                col.ColumnName = "column" + counter.ToString();
                counter++;
            }
            //format the report definition xml
            byte[] reportDefinitionBytes = Encoding.UTF8.GetBytes(ConfigurXMLReport(ReportPath, "CustomReportDs", columns).OuterXml);
            //load the formatted report into the reportviewer
            MemoryStream stream = new MemoryStream(reportDefinitionBytes);
            ReportViewer1.LocalReport.LoadReportDefinition(stream);
            //bind and display the data as normal
            ReportDataSource source = new ReportDataSource("DataSet1", data);
            ReportViewer1.LocalReport.DataSources.Clear();
            ReportViewer1.LocalReport.DataSources.Add(source);
            ReportViewer1.DataBind();
            ReportViewer1.LocalReport.Refresh();

最后我有了这个方法,它是我在研究问题时发现的其他人编写的几种方法的修改版本

Finally I have this method, which is a modified version of several methods written by others that I found during my research on the problem

public static XmlDocument ConfigurXMLReport(string path, Dictionary<string, string> Columns)
    {
        XmlDocument objXmlDocument = new XmlDocument();
        objXmlDocument.Load(path);
        XmlNamespaceManager mgr = new XmlNamespaceManager(objXmlDocument.NameTable);
        string uri = "http://schemas.microsoft.com/sqlserver/reporting/2008/01/reportdefinition";
        mgr.AddNamespace("df", uri);

        //locate and create nodes for cloning and modification
        XmlNode tablixCols = objXmlDocument.SelectSingleNode("/df:Report/df:Body/df:ReportItems/df:Tablix/df:TablixBody/df:TablixColumns", mgr);

        XmlNode dataField = objXmlDocument.SelectSingleNode("/df:Report/df:DataSets/df:DataSet/df:Fields/df:Field", mgr);

        XmlNode tablixMember = objXmlDocument.SelectSingleNode("/df:Report/df:Body/df:ReportItems/df:Tablix/df:TablixColumnHierarchy/df:TablixMembers/df:TablixMember", mgr);

        XmlNode rowHeaders = objXmlDocument.SelectSingleNode("/df:Report/df:Body/df:ReportItems/df:Tablix/df:TablixBody/df:TablixRows/df:TablixRow", mgr);
        XmlNode rowValues = rowHeaders.NextSibling.SelectSingleNode("./df:TablixCells", mgr);
        rowHeaders = rowHeaders.SelectSingleNode("./df:TablixCells", mgr);

        XmlNode sampleCol = tablixCols.SelectSingleNode("./df:TablixColumn", mgr);
        XmlNode sampleHeader = rowHeaders.SelectSingleNode("./df:TablixCell", mgr);
        XmlNode sampleValue = rowValues.SelectSingleNode("./df:TablixCell", mgr);
        //Iterate through the column definitions and add nodes to the xml to support the columns
        foreach (KeyValuePair<string,string> column in Columns)
        {
            //clone the sample nodes into new nodes
            XmlNode newDataField = dataField.CloneNode(true);
            newDataField.SelectSingleNode("./df:DataField", mgr).InnerText = column.Key;
            newDataField.Attributes["Name"].Value = column.Key;
            dataField.ParentNode.AppendChild(newDataField);

            XmlNode newCol = sampleCol.CloneNode(true);
            XmlNode newHeader = sampleHeader.CloneNode(true);
            XmlNode newValue = sampleValue.CloneNode(true);

            //update the new nodes with the column data
            newHeader.SelectSingleNode("./df:CellContents/df:Textbox", mgr).Attributes["Name"].Value = "Header" + column.Key;
            newValue.SelectSingleNode("./df:CellContents/df:Textbox", mgr).Attributes["Name"].Value = "Value" + column.Key;

            //because I use friendly column names - modify the report output to use the friendly name as the display value
            newHeader.SelectSingleNode("./df:CellContents/df:Textbox/df:Paragraphs/df:Paragraph/df:TextRuns/df:TextRun/df:Value", mgr).InnerText = column.Value;
            newValue.SelectSingleNode("./df:CellContents/df:Textbox/df:Paragraphs/df:Paragraph/df:TextRuns/df:TextRun/df:Value", mgr).InnerText = string.Format("=Fields!{0}.Value", column.Key);

            //add the new nodes to the document
            tablixCols.AppendChild(newCol);
            rowHeaders.AppendChild(newHeader);
            rowValues.AppendChild(newValue);

            tablixMember.ParentNode.AppendChild(tablixMember.CloneNode(true));
        }

        //remove the nodes used for cloning
        objXmlDocument.SelectSingleNode("/df:Report/df:DataSets/df:DataSet/df:Fields", mgr).RemoveChild(dataField);
        objXmlDocument.SelectSingleNode("/df:Report/df:Body/df:ReportItems/df:Tablix/df:TablixColumnHierarchy/df:TablixMembers", mgr).RemoveChild(tablixMember);
        tablixCols.RemoveChild(sampleCol);
        rowHeaders.RemoveChild(sampleHeader);
        rowValues.RemoveChild(sampleValue);
        //return the completed report definition
        return objXmlDocument;
    }

非常感谢这篇文章,旨在使我指出正确的方向.

Many thanks to this article for getting me pointed in the right direction.

这篇关于无法在ReportViewer aspx.net中显示数据表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆