123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620 |
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using FastReport.Utils;
- using FastReport.Data;
- using System.Drawing.Design;
- namespace FastReport
- {
- /// <summary>
- /// This class represents the Data band.
- /// </summary>
- /// <remarks>
- /// Use the <see cref="DataSource"/> property to connect the band to a datasource. Set the
- /// <see cref="Filter"/> property if you want to filter data rows. The <see cref="Sort"/>
- /// property can be used to sort data rows.
- /// </remarks>
- public partial class DataBand : BandBase
- {
- #region Fields
- private DataHeaderBand header;
- private DataFooterBand footer;
- private BandCollection bands;
- private DataSourceBase dataSource;
- private SortCollection sort;
- private string filter;
- private BandColumns columns;
- private bool printIfDetailEmpty;
- private bool printIfDatasourceEmpty;
- private bool keepTogether;
- private bool keepDetail;
- private string idColumn;
- private string parentIdColumn;
- private float indent;
- private bool keepSummary;
- private Relation relation;
- private bool collectChildRows;
- private int rowCount;
- private int maxRows;
- private bool resetPageNumber;
- #endregion
- #region Properties
- /// <summary>
- /// Gets or sets a header band.
- /// </summary>
- [Browsable(false)]
- public DataHeaderBand Header
- {
- get { return header; }
- set
- {
- SetProp(header, value);
- header = value;
- }
- }
- /// <summary>
- /// Gets a collection of detail bands.
- /// </summary>
- [Browsable(false)]
- public BandCollection Bands
- {
- get { return bands; }
- }
- /// <summary>
- /// Gets or sets a footer band.
- /// </summary>
- [Browsable(false)]
- public DataFooterBand Footer
- {
- get { return footer; }
- set
- {
- SetProp(footer, value);
- footer = value;
- }
- }
- /// <summary>
- /// Gets or sets a data source.
- /// Please note: data source have to be enabled.
- /// </summary>
- [Category("Data")]
- public DataSourceBase DataSource
- {
- get
- {
- if (dataSource != null && !dataSource.Enabled)
- return null;
- return dataSource;
- }
- set
- {
- if (dataSource != value)
- {
- if (dataSource != null)
- dataSource.Disposed -= new EventHandler(DataSource_Disposed);
- if (value != null)
- value.Disposed += new EventHandler(DataSource_Disposed);
- }
- dataSource = value;
- }
- }
- /// <summary>
- /// Gets or sets a number of rows in the virtual data source.
- /// </summary>
- /// <remarks>
- /// Use this property if your data band is not connected to any data source. In this case
- /// the virtual data source with the specified number of rows will be used.
- /// </remarks>
- [Category("Data")]
- [DefaultValue(1)]
- public int RowCount
- {
- get { return rowCount; }
- set { rowCount = value; }
- }
- /// <summary>
- /// Limits the maximum number of rows in a datasource. 0 means no limit.
- /// </summary>
- [Category("Data")]
- [DefaultValue(0)]
- public int MaxRows
- {
- get { return maxRows; }
- set { maxRows = value; }
- }
- /// <summary>
- /// Gets or sets a relation used to establish a master-detail relationship between
- /// this band and its parent.
- /// </summary>
- /// <remarks>
- /// Use this property if there are several relations exist between two data sources.
- /// If there is only one relation (in most cases it is), you can leave this property empty.
- /// </remarks>
- [Category("Data")]
- [Editor("FastReport.TypeEditors.RelationEditor, FastReport", typeof(UITypeEditor))]
- public Relation Relation
- {
- get { return relation; }
- set { relation = value; }
- }
- /// <summary>
- /// Gets the collection of sort conditions.
- /// </summary>
- [Browsable(false)]
- public SortCollection Sort
- {
- get { return sort; }
- }
- /// <summary>
- /// Gets the row filter expression.
- /// </summary>
- /// <remarks>
- /// This property can contain any valid boolean expression. If the expression returns <b>false</b>,
- /// the corresponding data row will not be printed.
- /// </remarks>
- [Category("Data")]
- [Editor("FastReport.TypeEditors.ExpressionEditor, FastReport", typeof(UITypeEditor))]
- public string Filter
- {
- get { return filter; }
- set { filter = value; }
- }
- /// <summary>
- /// Gets the band columns.
- /// </summary>
- [Category("Appearance")]
- [Editor("FastReport.TypeEditors.DataBandColumnEditor, FastReport", typeof(UITypeEditor))]
- public BandColumns Columns
- {
- get { return columns; }
- }
- /// <summary>
- /// Gets or sets a value that determines whether to print a band if all its detail rows are empty.
- /// </summary>
- [DefaultValue(false)]
- [Category("Behavior")]
- public bool PrintIfDetailEmpty
- {
- get { return printIfDetailEmpty; }
- set { printIfDetailEmpty = value; }
- }
- /// <summary>
- /// Gets or sets a value that determines whether to print a band if its datasource is empty.
- /// </summary>
- [DefaultValue(false)]
- [Category("Behavior")]
- public bool PrintIfDatasourceEmpty
- {
- get { return printIfDatasourceEmpty; }
- set { printIfDatasourceEmpty = value; }
- }
- /// <summary>
- /// Gets or sets a value indicating that all band rows should be printed together on one page.
- /// </summary>
- [DefaultValue(false)]
- [Category("Behavior")]
- public bool KeepTogether
- {
- get { return keepTogether; }
- set { keepTogether = value; }
- }
- /// <summary>
- /// Gets or sets a value indicating that the band should be printed together with all its detail rows.
- /// </summary>
- [DefaultValue(false)]
- [Category("Behavior")]
- public bool KeepDetail
- {
- get { return keepDetail; }
- set { keepDetail = value; }
- }
- /// <summary>
- /// Gets or sets the key column that identifies the data row.
- /// </summary>
- /// <remarks>
- /// <para>This property is used when printing a hierarchic list.</para>
- /// <para>To print the hierarchic list, you have to setup three properties: <b>IdColumn</b>,
- /// <b>ParentIdColumn</b> and <b>Indent</b>. First two properties are used to identify the data
- /// row and its parent; the <b>Indent</b> property specifies the indent that will be used to shift
- /// the databand according to its hierarchy level.</para>
- /// <para/>When printing hierarchy, FastReport shifts the band to the right
- /// (by value specified in the <see cref="Indent"/> property), and also decreases the
- /// width of the band by the same value. You may use the <b>Anchor</b> property of the
- /// objects on a band to indicate whether the object should move with the band, or stay
- /// on its original position, or shrink.
- /// </remarks>
- [Category("Hierarchy")]
- [Editor("FastReport.TypeEditors.DataColumnEditor, FastReport", typeof(UITypeEditor))]
- public string IdColumn
- {
- get { return idColumn; }
- set { idColumn = value; }
- }
- /// <summary>
- /// Gets or sets the column that identifies the parent data row.
- /// </summary>
- /// <remarks>
- /// This property is used when printing a hierarchic list. See description of the
- /// <see cref="IdColumn"/> property for more details.
- /// </remarks>
- [Category("Hierarchy")]
- [Editor("FastReport.TypeEditors.DataColumnEditor, FastReport", typeof(UITypeEditor))]
- public string ParentIdColumn
- {
- get { return parentIdColumn; }
- set { parentIdColumn = value; }
- }
- /// <summary>
- /// Gets or sets the indent that will be used to shift the databand according to its hierarchy level.
- /// </summary>
- /// <remarks>
- /// This property is used when printing a hierarchic list. See description of the
- /// <see cref="IdColumn"/> property for more details.
- /// </remarks>
- [DefaultValue(37.8f)]
- [Category("Hierarchy")]
- [TypeConverter("FastReport.TypeConverters.UnitsConverter, FastReport")]
- public float Indent
- {
- get { return indent; }
- set { indent = value; }
- }
- /// <summary>
- /// Gets or sets a value indicating that the databand should collect child data rows.
- /// </summary>
- /// <remarks>
- /// This property determines how the master-detail report is printed. Default behavior is:
- /// <para/>MasterData row1
- /// <para/>-- DetailData row1
- /// <para/>-- DetailData row2
- /// <para/>-- DetailData row3
- /// <para/>MasterData row2
- /// <para/>-- DetailData row1
- /// <para/>-- DetailData row2
- /// <para/>When you set this property to <b>true</b>, the master databand will collect all child data rows
- /// under a single master data row:
- /// <para/>MasterData row1
- /// <para/>-- DetailData row1
- /// <para/>-- DetailData row2
- /// <para/>-- DetailData row3
- /// <para/>-- DetailData row4
- /// <para/>-- DetailData row5
- /// </remarks>
- [DefaultValue(false)]
- [Category("Behavior")]
- public bool CollectChildRows
- {
- get { return collectChildRows; }
- set { collectChildRows = value; }
- }
- /// <summary>
- /// Gets or sets a value that determines whether to reset the page numbers when this band starts print.
- /// </summary>
- /// <remarks>
- /// Typically you should set the <see cref="BandBase.StartNewPage"/> property to <b>true</b> as well.
- /// </remarks>
- [DefaultValue(false)]
- [Category("Behavior")]
- public bool ResetPageNumber
- {
- get { return resetPageNumber; }
- set { resetPageNumber = value; }
- }
- internal bool IsDeepmostDataBand
- {
- get { return Bands.Count == 0; }
- }
- internal bool KeepSummary
- {
- get { return keepSummary; }
- set { keepSummary = value; }
- }
- internal bool IsHierarchical
- {
- get
- {
- return !String.IsNullOrEmpty(IdColumn) && !String.IsNullOrEmpty(ParentIdColumn);
- }
- }
- internal bool IsDatasourceEmpty
- {
- get { return DataSource == null || DataSource.RowCount == 0; }
- }
- #endregion
- #region Private Methods
- private void DataSource_Disposed(object sender, EventArgs e)
- {
- dataSource = null;
- }
- #endregion
- #region Protected Methods
- /// <inheritdoc/>
- protected override void DeserializeSubItems(FRReader reader)
- {
- if (String.Compare(reader.ItemName, "Sort", true) == 0)
- reader.Read(Sort);
- else
- base.DeserializeSubItems(reader);
- }
- #endregion
- #region IParent
- /// <inheritdoc/>
- public override void GetChildObjects(ObjectCollection list)
- {
- base.GetChildObjects(list);
- if (IsRunning)
- return;
- list.Add(header);
- foreach (BandBase band in bands)
- {
- list.Add(band);
- }
- list.Add(footer);
- }
- /// <inheritdoc/>
- public override bool CanContain(Base child)
- {
- return base.CanContain(child) || (child is DataHeaderBand || child is DataFooterBand ||
- child is DataBand || child is GroupHeaderBand);
- }
- /// <inheritdoc/>
- public override void AddChild(Base child)
- {
- if (IsRunning)
- {
- base.AddChild(child);
- return;
- }
- if (child is DataHeaderBand)
- Header = child as DataHeaderBand;
- else if (child is DataFooterBand)
- Footer = child as DataFooterBand;
- else if (child is DataBand || child is GroupHeaderBand)
- bands.Add(child as BandBase);
- else
- base.AddChild(child);
- }
- /// <inheritdoc/>
- public override void RemoveChild(Base child)
- {
- base.RemoveChild(child);
- if (IsRunning)
- return;
- if (child is DataHeaderBand && header == child as DataHeaderBand)
- Header = null;
- if (child is DataFooterBand && footer == child as DataFooterBand)
- Footer = null;
- if (child is DataBand || child is GroupHeaderBand)
- bands.Remove(child as BandBase);
- }
- /// <inheritdoc/>
- public override int GetChildOrder(Base child)
- {
- if (child is BandBase && !IsRunning)
- return bands.IndexOf(child as BandBase);
- return base.GetChildOrder(child);
- }
- /// <inheritdoc/>
- public override void SetChildOrder(Base child, int order)
- {
- if (child is BandBase && !IsRunning)
- {
- if (order > bands.Count)
- order = bands.Count;
- int oldOrder = child.ZOrder;
- if (oldOrder != -1 && order != -1 && oldOrder != order)
- {
- if (oldOrder <= order)
- order--;
- bands.Remove(child as BandBase);
- bands.Insert(order, child as BandBase);
- }
- }
- else
- base.SetChildOrder(child, order);
- }
- #endregion
- #region Public Methods
- /// <inheritdoc/>
- public override void Assign(Base source)
- {
- base.Assign(source);
- DataBand src = source as DataBand;
- DataSource = src.DataSource;
- RowCount = src.RowCount;
- MaxRows = src.MaxRows;
- Relation = src.Relation;
- Sort.Assign(src.Sort);
- Filter = src.Filter;
- Columns.Assign(src.Columns);
- PrintIfDetailEmpty = src.PrintIfDetailEmpty;
- PrintIfDatasourceEmpty = src.PrintIfDatasourceEmpty;
- KeepTogether = src.KeepTogether;
- KeepDetail = src.KeepDetail;
- IdColumn = src.IdColumn;
- ParentIdColumn = src.ParentIdColumn;
- Indent = src.Indent;
- CollectChildRows = src.CollectChildRows;
- ResetPageNumber = src.ResetPageNumber;
- }
- internal override void UpdateWidth()
- {
- if (Columns.Count > 1)
- {
- Width = Columns.ActualWidth;
- }
- else if (!String.IsNullOrEmpty(IdColumn) && !String.IsNullOrEmpty(ParentIdColumn))
- {
- if (PageWidth != 0)
- Width = PageWidth - Left;
- }
- else
- base.UpdateWidth();
- }
- /// <inheritdoc/>
- public override void Serialize(FRWriter writer)
- {
- DataBand c = writer.DiffObject as DataBand;
- base.Serialize(writer);
- if (writer.SerializeTo == SerializeTo.Preview)
- return;
- if (DataSource != c.DataSource)
- writer.WriteRef("DataSource", DataSource);
- if (RowCount != c.RowCount)
- writer.WriteInt("RowCount", RowCount);
- if (MaxRows != c.MaxRows)
- writer.WriteInt("MaxRows", MaxRows);
- if (Relation != c.Relation)
- writer.WriteRef("Relation", Relation);
- if (Sort.Count > 0)
- writer.Write(Sort);
- if (Filter != c.Filter)
- writer.WriteStr("Filter", Filter);
- Columns.Serialize(writer, c.Columns);
- if (PrintIfDetailEmpty != c.PrintIfDetailEmpty)
- writer.WriteBool("PrintIfDetailEmpty", PrintIfDetailEmpty);
- if (PrintIfDatasourceEmpty != c.PrintIfDatasourceEmpty)
- writer.WriteBool("PrintIfDatasourceEmpty", PrintIfDatasourceEmpty);
- if (KeepTogether != c.KeepTogether)
- writer.WriteBool("KeepTogether", KeepTogether);
- if (KeepDetail != c.KeepDetail)
- writer.WriteBool("KeepDetail", KeepDetail);
- if (IdColumn != c.IdColumn)
- writer.WriteStr("IdColumn", IdColumn);
- if (ParentIdColumn != c.ParentIdColumn)
- writer.WriteStr("ParentIdColumn", ParentIdColumn);
- if (FloatDiff(Indent, c.Indent))
- writer.WriteFloat("Indent", Indent);
- if (CollectChildRows != c.CollectChildRows)
- writer.WriteBool("CollectChildRows", CollectChildRows);
- if (ResetPageNumber != c.ResetPageNumber)
- writer.WriteBool("ResetPageNumber", ResetPageNumber);
- }
- /// <inheritdoc/>
- public override string[] GetExpressions()
- {
- List<string> list = new List<string>();
- foreach (Sort sort in Sort)
- {
- list.Add(sort.Expression);
- }
- list.Add(Filter);
- return list.ToArray();
- }
- /// <summary>
- /// Initializes the data source connected to this band.
- /// </summary>
- public void InitDataSource()
- {
- if (DataSource == null)
- {
- DataSource = new VirtualDataSource();
- DataSource.SetReport(Report);
- }
- if (DataSource is VirtualDataSource)
- (DataSource as VirtualDataSource).VirtualRowsCount = RowCount;
- DataSourceBase parentDataSource = ParentDataBand == null ? null : ParentDataBand.DataSource;
- bool collectChildRows = ParentDataBand == null ? false : ParentDataBand.CollectChildRows;
- if (Relation != null)
- DataSource.Init(Relation, Filter, Sort, collectChildRows);
- else
- DataSource.Init(parentDataSource, Filter, Sort, collectChildRows);
- }
- internal bool IsDetailEmpty()
- {
- if (PrintIfDetailEmpty || Bands.Count == 0)
- return false;
- foreach (BandBase band in Bands)
- {
- if (!band.IsEmpty())
- return false;
- }
- return true;
- }
- internal override bool IsEmpty()
- {
- InitDataSource();
- if (IsDatasourceEmpty)
- return !PrintIfDatasourceEmpty;
- DataSource.First();
- while (DataSource.HasMoreRows)
- {
- if (!IsDetailEmpty())
- return false;
- DataSource.Next();
- }
- return true;
- }
- /// <inheritdoc/>
- public override void InitializeComponent()
- {
- base.InitializeComponent();
- KeepSummary = false;
- }
- #endregion
- /// <summary>
- /// Initializes a new instance of the <see cref="DataBand"/> class.
- /// </summary>
- public DataBand()
- {
- bands = new BandCollection(this);
- sort = new SortCollection();
- filter = "";
- columns = new BandColumns(this);
- idColumn = "";
- parentIdColumn = "";
- indent = 37.8f;
- rowCount = 1;
- SetFlags(Flags.HasSmartTag, true);
- }
- }
- }
|