Xtrareport 使用Savelayout及Loadlayout
来源:互联网 发布:python 求均值 方差 编辑:程序博客网 时间:2024/04/29 07:35
http://community.devexpress.com/forums/p/54467/183602.aspx
I've been struggling with several issues with XtraReports and thought it would be nice to share my solutions.
The scene
We use a custom data source that implements all the required interfaces. We allow the creation of reports via the user designer and reports are saved to our database or a file. When viewing or editing reports we set the reports datasource at runtime.
We are using 7.1.2
The issues
- On SaveLayout the datasource would be saved. This would end up being a broken version of our datasource
- On LoadLayout extra datasource components would get added (broken) and bindings would reference the wrong datasource.
- We need to be able to pass data to the report, such as title, filter string, image
- Script references would get lost on loading, previewing etc. thus breaking Preview mode
The Solution
We use a subclass of the XtraReport to make our required alterations. Here it is...
// A class to store datasource info while saving
public class MyReportData
{
public object DataSource = null;
public string DataMember = null;
public Dictionary<string, object> Parameters = null;
public object Tag = null;
}
// The modified XtraReport
// Provides ability to add name/value parameters to the report (Parameters property)
// IntialiseScriptReferences() will set any required script references as needed
// ExtractData() and RestoreData(MyReportData) should be used around SaveLayout and LoadLayout
// to ensure datasources dont get messed up
public class MyReport : DevExpress.XtraReports.UI.XtraReport
{
public MyReport()
{
this.IntialiseScriptReferences();
}
public void IntialiseScriptReferences()
{
// re-set the ScriptReferences
// This example will reference all assemblies (not good for security!)
List<String> assemblyLocations = new List<string>();
foreach (Assembly assembly in System.AppDomain.CurrentDomain.GetAssemblies())
{
assemblyLocations.Add(assembly.Location);
}
this.ScriptReferences = assemblyLocations.ToArray();
}
public static event EventHandler ReportInitialized = null;
protected override void OnReportInitialize()
{
// Cloans of reports are used to do previews. These cloans don't have the script references.
// This will add the required references to the cloan before it gets used.
// you should also have your designer listen to this event so it can call RestoreData()
// To setup the datasource for the cloan. Otherwise the preview will have no data!
base.OnReportInitialize();
this.IntialiseScriptReferences();
if (ReportInitialized != null)
ReportInitialized(this, EventArgs.Empty);
}
protected MyReportData GetData()
{
// Gather the datasource data from the report
MyReportData data = new MyReportData();
data.DataSource = this.DataSource;
data.DataMember = this.DataMember;
data.Parameters = this._Parameters;
data.Tag = this.Tag;
return data;
}
protected void ClearData()
{
/// remove all datasource references in the report
this.DataSource = null;
this.DataMember = null;
this._Parameters = null;
this.Tag = null;
RecursiveSetDataSources(null);
}
public MyReportData ExtractData()
{
// Gather the datasource data from the report then remove all datasource references
// This should be called before a SaveLayout or LoadLayout so no datasource info is
// included in the saved or loaded data
MyReportData data = GetData();
ClearData();
return data;
}
public void RestoreData(MyReportData data)
{
// re bind all references to the datasource
// This should be called after a SaveLayout or LoadLayout to re-establish the datasouces
RecursiveSetDataSources(data.DataSource);
this.DataSource = data.DataSource;
this.DataMember = data.DataMember;
this._Parameters = data.Parameters;
this.Tag = data.Tag;
}
protected void RecursiveSetDataSources(object datasource)
{
this.RecursiveSetDataSources(datasource, this);
}
private void RecursiveSetDataSources(object datasource, XRControl control)
{
// Iterate all controls in the report to change their datasource
// This assumes all bound controls are using the same datasource
if (control is XtraReportBase)
{
XtraReportBase reportControl = (XtraReportBase)control;
string member = reportControl.DataMember;
if (!String.IsNullOrEmpty(member)) // only set datasource if a datamember has been specified
{
reportControl.DataSource = datasource;
reportControl.DataMember = member; // reset member as setting datasource may null this out
}
}
// also make sure all Bindings are updated
foreach(XRBinding binding in control.DataBindings)
{
string member = binding.DataMember;
if (!String.IsNullOrEmpty(member))
{
binding.Assign(datasource,member);
}
}
// Do the recursive bit
if (control.HasChildren)
{
foreach (XRControl innerControl in control.Controls)
{
RecursiveSetDataSources(datasource, innerControl);
}
}
}
private Dictionary<string, object> _Parameters = null;
public Dictionary<string, object> Parameters
{
get
{
// this collection of data can be accessed via scripts in the report
// so data can be passed into the report such as titles, images
if (_Parameters==null)
{
this._Parameters = new Dictionary<string, object>();
}
return _Parameters;
}
}
}
// This is a designer class modified so it will bind the datasource correctly when previewing
// previewing uses a cloan of the report. We listent to the initialisation of all cloans, if its
// a cloan of our report then we bind the datasource
// To use this make sure you set the Report property
public partial class MyXRDesignForm : DevExpress.XtraReports.UserDesigner.XRDesignFormExBase
{
private MyReport _Report = null;
private string ReportTag = null;
private MyReportData MyReportData = null;
public MyXRDesignForm()
{
InitializeComponent();
// listen to all reports being initialised
MyReport.ReportInitialized += new EventHandler(Report_ReportInitialized);
}
public MyReport Report
{
get
{
return _Report;
}
set
{
if (_Report != value)
{
if (_Report != null)
{
_Report.Tag = null;
}
_Report = value;
if (_Report != null)
{
// get the datasource so we can bind cloaned reports to it
this.MyReportData = _Report.GetData();
// store tracking info to determine if a report is ours
this.ReportTag = "Report" + DateTime.Now.Ticks.ToString();
_Report.Tag = this.ReportTag;
}
else
this.MyReportData = null;
}
}
}
void Report_ReportInitialized(object sender, EventArgs e)
{
MyReport report = (MyReport)sender;
// check if its our report. if so then bind the datasource
if (this.ReportTag != null && report.Tag != null && this.ReportTag == report.Tag.ToString())
report.RestoreData(this.MyReportData);
}
}
Whenever you do a SaveLayout or LoadLayout you should use this template...
MyReportData myReportData = null;
try
{
myReportData = report.ExtractData();
report.SaveLayout(stream); // or report.LoadLayout(stream)
}
finally
{
report.RestoreData(myReportData);
}
I hope this is helpful
Disclaimer: The code is a modified version of the one we use. It has not been tested or compiled so it may contain bugs and syntax errors.
Tony McCreath
- Xtrareport 使用Savelayout及Loadlayout
- xtrareport的使用心得
- XtraReport控件的使用
- DevExpress的XtraReport使用积累
- xtraReport使用之End User篇
- xtraReport使用之End User篇二
- 我对bds2006中使用xtrareport做报表的探索
- devexpress xtrareport
- 使用DevExpress.XtraReports.UI.XtraReport 设计报表的时候如何格式化字符串
- XtraReport的应用
- XtraReport的汉字支持
- XtraReport报表使用手记
- xtraReport save to DB
- devexpress xtraReport 汉化功能
- Devexpress xtrareport参考资料
- dev XtraReport 做报表
- XtraReport显示行序号
- 关于DevExpress xtragrid xtrareport小记
- HTTP 协议基础,http头信息详解
- 整数转换成字符串
- 利用可变数组将用户输入数字排序后输出
- java版本的escape和unescape函数
- 反转32 位数
- Xtrareport 使用Savelayout及Loadlayout
- C# 集合类之 Dictionary 泛型集合
- 徐家骏:我在华为工作十年的感悟
- “Compiling... ,Error spawning cl.exe”错误
- 控制 TextBox 输入时若是英文自动转大写或转小写的方法
- 用 Firebug 动态调试和优化应用程序
- 网页常用Javascript
- Lex和Yacc使用学习笔记(二)
- 今天调休