using System; using System.Data; using System.ComponentModel; using System.Reflection; using System.Collections; using FastReport.Utils; using System.IO; using System.Drawing.Design; namespace FastReport.Data { /// /// Represents a datasource based on DataTable class. /// /// This example shows how to add a new table to the existing connection: /// /// Report report1; /// DataConnectionBase conn = report1.Dictionary.Connections.FindByName("Connection1"); /// TableDataSource table = new TableDataSource(); /// table.TableName = "Employees"; /// table.Name = "Table1"; /// conn.Tables.Add(table); /// /// public partial class TableDataSource : DataSourceBase { #region Fields private DataTable table; private string tableName; private string selectCommand; private CommandParameterCollection parameters; private bool storeData; private bool ignoreConnection; private string qbSchema; #endregion #region Properties /// /// Gets or sets the underlying DataTable object. /// [Browsable(false)] public DataTable Table { get { return table; } set { table = value; } } /// /// Gets or sets the table name. /// [Category("Data")] public string TableName { get { return tableName; } set { tableName = value; } } /// /// Gets or sets SQL "select" command. /// /// /// If this command contains parameters, you should specify them in the /// property. /// [Category("Data")] [Editor("FastReport.TypeEditors.SqlEditor, FastReport", typeof(UITypeEditor))] public string SelectCommand { get { return selectCommand; } set { selectCommand = value; } } /// /// Gets a collection of parameters used by "select" command. /// /// /// You must set up this property if the SQL query that you've specified in the /// property contains parameters. /// You can pass a value to the SQL parameter in two ways. /// The right way is to define a report parameter. You can do this in the /// "Data" window. Once you have defined the parameter, you can use it to pass a value /// to the SQL parameter. To do this, set the SQL parameter's Expression property /// to the report parameter's name (so it will look like [myReportParam]). /// To pass a value to the report parameter from your application, use the /// method. /// The other way (unrecommended) is to find a datasource object and set its parameter from a code: /// /// TableDataSource ds = report.GetDataSource("My DataSource Name") as TableDataSource; /// ds.Parameters[0].Value = 10; /// /// This way is not good because you hardcode the report object's name. /// [Category("Data")] [Editor("FastReport.TypeEditors.CommandParametersEditor, FastReport", typeof(UITypeEditor))] public CommandParameterCollection Parameters { get { return parameters; } set { parameters = value; } } /// /// Gets or sets the parent object. /// [Browsable(false)] public DataConnectionBase Connection { get { return IgnoreConnection ? null : Parent as DataConnectionBase; } set { Parent = value; } } /// /// Gets or sets a value that determines whether it is necessary to store table data in a report file. /// [Category("Data")] [DefaultValue(false)] public bool StoreData { get { return storeData; } set { storeData = value; } } /// /// Gets or sets the table data. /// /// /// This property is for internal use only. /// [Browsable(false)] public virtual string TableData { get { string result = ""; if (Table == null && Connection != null) { Connection.CreateTable(this); Connection.FillTable(this); } if (Table != null) { using (DataSet tempDs = new DataSet()) { DataTable tempTable = Table.Copy(); tempDs.Tables.Add(tempTable); using (MemoryStream stream = new MemoryStream()) { tempDs.WriteXml(stream, XmlWriteMode.WriteSchema); result = Convert.ToBase64String(stream.ToArray()); } tempTable.Dispose(); } } return result; } set { if(!string.IsNullOrEmpty(value)) { using (MemoryStream stream = new MemoryStream(Convert.FromBase64String(value))) using (DataSet tempDs = new DataSet()) { tempDs.ReadXml(stream); table = tempDs.Tables[0]; Reference = table; tempDs.Tables.RemoveAt(0); } } } } /// /// If set, ignores the Connection (always returns null). Needed when we replace the /// existing connection-based datasource with datatable defined in an application. /// internal bool IgnoreConnection { get { return ignoreConnection; } set { ignoreConnection = value; } } /// /// Gets or sets the query builder schema. /// /// /// This property is for internal use only. /// [Browsable(false)] public string QbSchema { get { return qbSchema; } set { qbSchema = value; } } #endregion #region Private Methods private Column CreateColumn(DataColumn column) { Column c = new Column(); c.Name = column.ColumnName; c.Alias = column.Caption; c.DataType = column.DataType; c.SetBindableControlType(c.DataType); return c; } private void DeleteTable() { if (Connection != null) Connection.DeleteTable(this); } private void CreateColumns() { Columns.Clear(); if (Table != null) { foreach (DataColumn column in Table.Columns) { Column c = CreateColumn(column); Columns.Add(c); } } } #endregion #region Protected Methods /// protected override void Dispose(bool disposing) { if (disposing) DeleteTable(); base.Dispose(disposing); } /// protected override object GetValue(Column column) { if (column == null) return null; if (column.Tag == null) { int index = Table.Columns.IndexOf(column.Name); if (index == -1) return null; column.Tag = index; } return CurrentRow == null ? null : ((DataRow)CurrentRow)[(int)column.Tag]; } #endregion #region Public Methods /// public override void InitSchema() { if (Connection != null) { if (!StoreData) { Connection.CreateTable(this); if (Table.Columns.Count == 0) Connection.FillTableSchema(Table, SelectCommand, Parameters); } } else table = Reference as DataTable; if (Columns.Count == 0) CreateColumns(); foreach (Column column in Columns) { column.Tag = null; } } /// public override void LoadData(ArrayList rows) { if (Connection != null) { if (!StoreData) Connection.FillTable(this); } else { TryToLoadData(); } if (Table == null) throw new DataTableException(Alias); // custom load data via Load event OnLoad(); bool needReload = ForceLoadData || rows.Count == 0 || Parameters.Count > 0; if (needReload) { // fill rows rows.Clear(); foreach (DataRow row in Table.Rows) { if (row.RowState != DataRowState.Deleted && row.RowState != DataRowState.Detached) rows.Add(row); } } } /// /// Refresh the table schema. /// public void RefreshTable() { DeleteTable(); InitSchema(); RefreshColumns(true); } internal void RefreshColumns(bool enableNew) { if (Table != null) { // add new columns foreach (DataColumn column in Table.Columns) { if (Columns.FindByName(column.ColumnName) == null) { Column c = CreateColumn(column); c.Enabled = enableNew; Columns.Add(c); } } // delete obsolete columns int i = 0; while (i < Columns.Count) { Column c = Columns[i]; if (!c.Calculated && !Table.Columns.Contains(c.Name)) c.Dispose(); else i++; } } } /// public override void Serialize(FRWriter writer) { base.Serialize(writer); if (!String.IsNullOrEmpty(TableName)) writer.WriteStr("TableName", TableName); if (!String.IsNullOrEmpty(SelectCommand)) writer.WriteStr("SelectCommand", SelectCommand); if (!String.IsNullOrEmpty(QbSchema)) writer.WriteStr("QbSchema", QbSchema); if (StoreData) { writer.WriteBool("StoreData", true); writer.WriteStr("TableData", TableData); } } /// public override void SetParent(Base value) { base.SetParent(value); SetFlags(Flags.CanEdit, Connection != null); } /// public override void InitializeComponent() { base.InitializeComponent(); foreach (CommandParameter par in Parameters) { par.ResetLastValue(); } } #endregion #region IParent Members /// public override bool CanContain(Base child) { return base.CanContain(child) || child is CommandParameter; } /// public override void GetChildObjects(ObjectCollection list) { base.GetChildObjects(list); foreach (CommandParameter p in Parameters) { list.Add(p); } } /// public override void AddChild(Base child) { if (child is CommandParameter) Parameters.Add(child as CommandParameter); else base.AddChild(child); } /// public override void RemoveChild(Base child) { if (child is CommandParameter) Parameters.Remove(child as CommandParameter); else base.RemoveChild(child); } #endregion /// /// Initializes a new instance of the class with default settings. /// public TableDataSource() { TableName = ""; SelectCommand = ""; QbSchema = ""; parameters = new CommandParameterCollection(this); } } }