本文为实现在水晶报表中显示任意列,并且无论显示多少列,要保持列宽总和不变,即当显示的列数比较少时,不能让其“缩”在左侧,而导致右侧一片放空,就是要实现根据列数的多少让其具有“自动拉伸”的效果。
本文实现的效果是显示3~8列,望能给各位起到一定的参考作用:
因最多显示8列,故先在模板放置8个字段对象
模板看似简单,但它对尺寸的控制要求很高,不仅每个对象大小要保持一样,并且对对象间的间距控制也半点马虎不得,比如这里每个对象的宽度为1353,列1的Left属性为105,所以列2的Left属性=105+1353+40=1498,列3的Left属性=1498+1353+40……依此类推得其余列的Left属性值,中间的40是对象边框的宽度。这边模板的精确设计是为了获得 列宽总和,因为这个列宽总和始终保持不变,无论当前显示多少列
最少显示3列,故对后面五列设置抑制显示,当然要加上抑制显示条件,其中有一个参数字段OptionNum,表示当前要显示的总列数
模板就是这样,我们再来看看关键代码段,本文最最关键的正是如何动态控制对象的尺寸并以此来达到“自动拉伸”的效果
- /// <summary>
- /// 强类型数据集,水晶报表“骨架”
- /// </summary>
- DataSet1 myDataSet = new DataSet1();
- /// <summary>
- /// “查看报表”按钮事件
- /// </summary>
- private void btnShowReport_Click(object sender, EventArgs e)
- {
- int DisplayColumnNum;
- if (!int.TryParse(comboBox1.Text, out DisplayColumnNum))
- {
- DisplayColumnNum = 8; //默认显示8列
- }
- //把要显示的列数以参数形式传给水晶报表
- myReport.SetParameterValue("OptionNum", DisplayColumnNum);
- DisplayColumnByN(DisplayColumnNum);//这里尺寸控制是关键
- crystalReportViewer1.ReportSource = myReport;
- }
- /// <summary>
- /// 控制报表显示的列数及其尺寸控制
- /// 无论显示多少列,控制所有列宽的总和保持一致
- /// 【本方法也正是本文最最核心的片段】
- /// </summary>
- /// <param name="N">欲显示的列数</param>
- private void DisplayColumnByN(int N)
- {
- /****************特 别 说 明************************************
- * 前面精确的模板设计至关重要,半点马虎不得,最终的效果都在此一举
- * 因为我们对每个对象加了左右边框,在水晶报表里面,‘单线’边框占
- * 40(di),勿忘了考虑这个宽度。
- * 在设计的时候,我把两个相邻对象之间的右边框和左边框“叠”在了一起,
- * 所以两个对象间只需考虑一个40,不用考虑2*40=80(di)单位的宽度 */
- //由于列宽总和要保持一致,故需先获取总宽度
- int tableWidth = 1353 * 8 + 7 * 40; //1353为对象宽度,40为边框宽度
- //设置当前每一列的宽度,必须先减掉中间边框的宽度再均分
- int columnWidth = (tableWidth - (N - 1) * 40) / N;
- //标识 列序号
- int columnOrder = 1;
- //遍历详细节的对象
- foreach (ReportObject obj in ((CrystalReport1)myReport).Section3.ReportObjects)
- {
- //列1的Left属性(105)保持不变
- obj.Left = 105 + (columnWidth + 40) * (columnOrder - 1);
- obj.Width = columnWidth;
- columnOrder++;
- }
- }
- /// <summary>
- /// 全局水晶报表对象
- /// </summary>
- ReportDocument myReport;
- /// <summary>
- /// 窗体关闭后立即删除水晶报表产生的临时文件,避免过多临时文件从而导致“报表加载失败”
- /// </summary>
- private void rptForm_FormClosing(object sender, FormClosingEventArgs e)
- {
- myReport.Dispose();
- }
- /// <summary>
- /// 填充水晶报表“骨架”并为水晶报表设定数据源
- /// </summary>
- private void rptForm_Load(object sender, EventArgs e)
- {
- //往数据集“塞”测试数据
- myDataSet.MultipleColTable.AddMultipleColTableRow("行一", "行一", "行一", "行一", "行一", "行一", "行一", "行一");
- myDataSet.MultipleColTable.AddMultipleColTableRow("行二", "行二", "行二", "行二", "行二", "行二", "行二", "行二");
- myDataSet.MultipleColTable.AddMultipleColTableRow("行三", "行三", "行三", "行三", "行三", "行三", "行三", "行三");
- myDataSet.MultipleColTable.AddMultipleColTableRow("行四", "行四", "行四", "行四", "行四", "行四", "行四", "行四");
- myDataSet.MultipleColTable.AddMultipleColTableRow("行五", "行五", "行五", "行五", "行五", "行五", "行五", "行五");
- myReport = new CrystalReport1();
- myReport.SetDataSource(myDataSet);
- }
最后的效果图