using System.ComponentModel;
using FastReport.Utils;
using FastReport.Data;
using System.Drawing.Design;
namespace FastReport
{
///
/// Specifies a sort order.
///
///
/// This enumeration is used in the group header and in the "Matrix" object.
///
public enum SortOrder
{
///
/// Specifies no sort (natural order).
///
None,
///
/// Specifies an ascending sort order.
///
Ascending,
///
/// Specifies a descending sort order.
///
Descending
}
///
/// Represents a group header band.
///
///
/// A simple group consists of one GroupHeaderBand and the DataBand that is set
/// to the property. To create the nested groups, use the property.
///
/// Only the last nested group can have data band.
///
/// Use the property to set the group condition. The
/// property can be used to set the sort order for group's data rows. You can also use the Sort
/// property of the group's DataBand to specify additional sort.
///
/// This example shows how to create nested groups.
///
/// ReportPage page = report.Pages[0] as ReportPage;
///
/// // create the main group
/// GroupHeaderBand mainGroup = new GroupHeaderBand();
/// mainGroup.Height = Units.Millimeters * 10;
/// mainGroup.Name = "MainGroup";
/// mainGroup.Condition = "[Orders.CustomerName]";
/// // add a group to the page
/// page.Bands.Add(mainGroup);
///
/// // create the nested group
/// GroupHeaderBand nestedGroup = new GroupHeaderBand();
/// nestedGroup.Height = Units.Millimeters * 10;
/// nestedGroup.Name = "NestedGroup";
/// nestedGroup.Condition = "[Orders.OrderDate]";
/// // add it to the main group
/// mainGroup.NestedGroup = nestedGroup;
///
/// // create a data band
/// DataBand dataBand = new DataBand();
/// dataBand.Height = Units.Millimeters * 10;
/// dataBand.Name = "GroupData";
/// dataBand.DataSource = report.GetDataSource("Orders");
/// // connect the databand to the nested group
/// nestedGroup.Data = dataBand;
///
///
public partial class GroupHeaderBand : HeaderFooterBandBase
{
#region Fields
private GroupHeaderBand nestedGroup;
private DataBand data;
private GroupFooterBand groupFooter;
private DataHeaderBand header;
private DataFooterBand footer;
private string condition;
private SortOrder sortOrder;
private bool keepTogether;
private bool resetPageNumber;
private object groupValue;
#endregion
#region Properties
///
/// Gets or sets a nested group.
///
///
/// Use this property to create nested groups.
///
/// Only the last nested group can have data band.
///
///
///
/// This example demonstrates how to create a group with nested group.
///
/// ReportPage page;
/// GroupHeaderBand group = new GroupHeaderBand();
/// group.NestedGroup = new GroupHeaderBand();
/// group.NestedGroup.Data = new DataBand();
/// page.Bands.Add(group);
///
///
[Browsable(false)]
public GroupHeaderBand NestedGroup
{
get { return nestedGroup; }
set
{
SetProp(nestedGroup, value);
nestedGroup = value;
}
}
///
/// Gets or sets the group data band.
///
///
/// Use this property to add a data band to a group. Note: only the last nested group can have Data band.
///
///
/// This example demonstrates how to add a data band to a group.
///
/// ReportPage page;
/// GroupHeaderBand group = new GroupHeaderBand();
/// group.Data = new DataBand();
/// page.Bands.Add(group);
///
///
[Browsable(false)]
public DataBand Data
{
get { return data; }
set
{
SetProp(data, value);
data = value;
}
}
///
/// Gets or sets a group footer.
///
[Browsable(false)]
public GroupFooterBand GroupFooter
{
get { return groupFooter; }
set
{
SetProp(groupFooter, value);
groupFooter = value;
}
}
///
/// Gets or sets a header band.
///
[Browsable(false)]
public DataHeaderBand Header
{
get { return header; }
set
{
SetProp(header, value);
header = value;
}
}
///
/// Gets or sets a footer band.
///
///
/// To access a group footer band, use the property.
///
[Browsable(false)]
public DataFooterBand Footer
{
get { return footer; }
set
{
SetProp(footer, value);
footer = value;
}
}
///
/// Gets or sets the group condition.
///
///
/// This property can contain any valid expression. When running a report, this expression is calculated
/// for each data row. When the value of this condition is changed, FastReport starts a new group.
///
[Category("Data")]
[Editor("FastReport.TypeEditors.ExpressionEditor, FastReport", typeof(UITypeEditor))]
public string Condition
{
get { return condition; }
set { condition = value; }
}
///
/// Gets or sets the sort order.
///
///
/// FastReport can sort data rows automatically using the value.
///
[DefaultValue(SortOrder.Ascending)]
[Category("Behavior")]
public SortOrder SortOrder
{
get { return sortOrder; }
set { sortOrder = value; }
}
///
/// Gets or sets a value indicating that the group should be printed together on one page.
///
[DefaultValue(false)]
[Category("Behavior")]
public bool KeepTogether
{
get { return keepTogether; }
set { keepTogether = value; }
}
///
/// Gets or sets a value that determines whether to reset the page numbers when this group starts print.
///
///
/// Typically you should set the property to true as well.
///
[DefaultValue(false)]
[Category("Behavior")]
public bool ResetPageNumber
{
get { return resetPageNumber; }
set { resetPageNumber = value; }
}
internal DataSourceBase DataSource
{
get
{
DataBand dataBand = GroupDataBand;
return dataBand == null ? null : dataBand.DataSource;
}
}
internal DataBand GroupDataBand
{
get
{
GroupHeaderBand group = this;
while (group != null)
{
if (group.Data != null)
return group.Data;
group = group.NestedGroup;
}
return null;
}
}
#endregion
#region IParent
///
public override void GetChildObjects(ObjectCollection list)
{
base.GetChildObjects(list);
if (!IsRunning)
{
list.Add(header);
list.Add(nestedGroup);
list.Add(data);
list.Add(groupFooter);
list.Add(footer);
}
}
///
public override bool CanContain(Base child)
{
return base.CanContain(child) ||
(child is DataBand && nestedGroup == null && data == null) ||
(child is GroupHeaderBand && (nestedGroup == null || nestedGroup is GroupHeaderBand) && data == null) ||
child is GroupFooterBand || child is DataHeaderBand || child is DataFooterBand;
}
///
public override void AddChild(Base child)
{
if (IsRunning)
{
base.AddChild(child);
return;
}
if (child is GroupHeaderBand)
NestedGroup = child as GroupHeaderBand;
else if (child is DataBand)
Data = child as DataBand;
else if (child is GroupFooterBand)
GroupFooter = child as GroupFooterBand;
else if (child is DataHeaderBand)
Header = child as DataHeaderBand;
else if (child is DataFooterBand)
Footer = child as DataFooterBand;
else
base.AddChild(child);
}
///
public override void RemoveChild(Base child)
{
base.RemoveChild(child);
if (IsRunning)
return;
if (child is GroupHeaderBand && nestedGroup == child)
NestedGroup = null;
if (child is DataBand && data == child as DataBand)
Data = null;
if (child is GroupFooterBand && groupFooter == child)
GroupFooter = null;
if (child is DataHeaderBand && header == child)
Header = null;
if (child is DataFooterBand && footer == child)
Footer = null;
}
#endregion
#region Public Methods
///
public override void Assign(Base source)
{
base.Assign(source);
GroupHeaderBand src = source as GroupHeaderBand;
Condition = src.Condition;
SortOrder = src.SortOrder;
KeepTogether = src.KeepTogether;
ResetPageNumber = src.ResetPageNumber;
}
///
public override void Serialize(FRWriter writer)
{
GroupHeaderBand c = writer.DiffObject as GroupHeaderBand;
base.Serialize(writer);
if (writer.SerializeTo == SerializeTo.Preview)
return;
if (Condition != c.Condition)
writer.WriteStr("Condition", Condition);
if (SortOrder != c.SortOrder)
writer.WriteValue("SortOrder", SortOrder);
if (KeepTogether != c.KeepTogether)
writer.WriteBool("KeepTogether", KeepTogether);
if (ResetPageNumber != c.ResetPageNumber)
writer.WriteBool("ResetPageNumber", ResetPageNumber);
}
///
public override string[] GetExpressions()
{
return new string[] { Condition };
}
internal override bool IsEmpty()
{
if (NestedGroup != null)
return NestedGroup.IsEmpty();
else if (Data != null)
return Data.IsEmpty();
return base.IsEmpty();
}
internal void InitDataSource()
{
DataBand dataBand = GroupDataBand;
GroupHeaderBand group = this;
int index = 0;
// insert group sort to the databand
while (group != null)
{
if (group.SortOrder != SortOrder.None)
{
dataBand.Sort.Insert(index, new Sort(group.Condition, group.SortOrder == SortOrder.Descending));
index++;
}
group = group.NestedGroup;
}
dataBand.InitDataSource();
}
internal void FinalizeDataSource()
{
DataBand dataBand = GroupDataBand;
GroupHeaderBand group = this;
// remove group sort from the databand
while (group != null)
{
if (group.SortOrder != SortOrder.None)
dataBand.Sort.RemoveAt(0);
group = group.NestedGroup;
}
}
internal void ResetGroupValue()
{
if (!string.IsNullOrEmpty(Condition))
{
groupValue = Report.Calc(Condition);
}
else
{
throw new GroupHeaderHasNoGroupCondition(Name);
}
}
internal bool GroupValueChanged()
{
object value = null;
if (!string.IsNullOrEmpty(Condition))
{
value = Report.Calc(Condition);
}
else
{
throw new GroupHeaderHasNoGroupCondition(Name);
}
if (groupValue == null)
{
if (value == null)
return false;
return true;
}
return !groupValue.Equals(value);
}
#endregion
///
/// Initializes a new instance of the class with default settings.
///
public GroupHeaderBand()
{
condition = "";
sortOrder = SortOrder.Ascending;
}
}
}