我无法在ReportViewer控件中显示DataTable对象的内容。没有错误,只有页面上显示空白的报表查看器。我查看了在here,here和here发现的各种类似问题中提出的解决方案 - 最后一个问题特别令人沮丧,因为最后一条评论说“让我们在聊天中继续讨论”没有提供答案,这基本上是我的确切问题。
网页代码:
<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数据属性似乎也有数据 - 它只是没有显示....
非常感谢任何帮助!
答案 0 :(得分:0)
因此,在经过大量研究和谷歌搜索以及来自我的优秀开发同事的帮助后,我遇到了一个解决方案,主要涉及重建.rdlc文件的xml结构以支持动态列。这种方法有几点需要注意。 1.您必须手动配置引用数据源的xml以指向提供数据表的对象方法,因为报表设计器不支持此操作。我在下面包含了我的xml更改。 2.您必须在报表定义中添加一个表,其中只有一列和一行。也许有人可以做得更好。
所以解决方案。首先是rdlc xml数据源配置:
<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>
接下来,您必须配置报表查看器以从内存流中接收报表定义:
//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();
最后我有这个方法,这是我在研究问题时发现的其他几种方法的修改版本
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;
}
非常感谢this文章让我指出了正确的方向。