/// <summary> /// 添加主从关系 /// </summary> /// <param name="ChildControlName"> /// 子控件名称 /// </param> /// <param name="ParentColumnName"> /// 对应父控件列名 /// </param> /// <param name="ChildColumnName"> /// 对应子控件列名 /// </param> public void AddRelation(string childControlName, string parentColumnName, string childColumnName) { DataBand db = this.Report.FindObject(childControlName) as DataBand; FastReport.Data.Relation relation = new FastReport.Data.Relation(); relation.ParentDataSource = (db.Parent as DataBand).DataSource; relation.ParentColumns = new string[] { parentColumnName }; relation.ChildColumns = new string[] { childColumnName }; db.Relation = relation; }
internal void Init(Relation relation, string filter, SortCollection sort, bool useAllParentRows) { if (FShowAccessDataMessage) { Config.ReportSettings.OnProgress(Report, Res.Get("Messages,AccessingData")); } // InitSchema may fail sometimes (for example, when using OracleConnection with nested select). try { InitSchema(); } catch { } LoadData(); // fill rows, emulate relation rows.Clear(); if (relation != null && relation.Enabled) { if (useAllParentRows) { DataSourceBase parentData = relation.ParentDataSource; // parentData must be initialized prior to calling this method! parentData.First(); while (parentData.HasMoreRows) { GetChildRows(relation); parentData.Next(); } } else { GetChildRows(relation); } } else { foreach (object row in InternalRows) { rows.Add(row); } } // filter data rows if (FShowAccessDataMessage && rows.Count > 10000) { Config.ReportSettings.OnProgress(Report, Res.Get("Messages,PreparingData")); } if (filter != null && filter.Trim() != "") { for (int i = 0; i < rows.Count; i++) { CurrentRowNo = i; object match = Report.Calc(filter); if (match is bool && !(bool)match) { rows.RemoveAt(i); i--; } } } // additional filter if (AdditionalFilter.Count > 0) { ApplyAdditionalFilter(); } // sort data rows if (sort != null && sort.Count > 0) { string[] expressions = new string[sort.Count]; bool[] descending = new bool[sort.Count]; for (int i = 0; i < sort.Count; i++) { expressions[i] = sort[i].Expression; descending[i] = sort[i].Descending; } rows.Sort(new RowComparer(Report, this, expressions, descending)); } FShowAccessDataMessage = false; First(); }
internal void Init(DataSourceBase parentData, string filter, SortCollection sort, bool useAllParentRows) { Relation relation = parentData != null?DataHelper.FindRelation(Report.Dictionary, parentData, this) : null; Init(relation, filter, sort, useAllParentRows); }
/// <summary> /// Initializes this datasource and filters data rows according to the master-detail relation. /// Also applies the specified filter and sorts the rows. /// </summary> /// <param name="relation">The master-detail relation.</param> /// <param name="filter">The filter expression.</param> /// <param name="sort">The collection of sort descriptors.</param> /// <remarks> /// To use master-detail relation, you must define the <see cref="Relation"/> object that describes /// the relation, and add it to the <b>Report.Dictionary.Relations</b> collection. /// </remarks> public void Init(Relation relation, string filter, SortCollection sort) { Init(relation, filter, sort, false); }
internal void FindParentRow(Relation relation) { InitSchema(); LoadData(); int columnCount = relation.ChildColumns.Length; object[] childValues = new object[columnCount]; for (int i = 0; i < columnCount; i++) { childValues[i] = relation.ChildDataSource[relation.ChildColumns[i]]; } object result = null; if (childValues[0] == null) { SetCurrentRow(null); return; } // improve performance for single column index if (columnCount == 1) { if (rowIndices.Count == 0) { foreach (object row in InternalRows) { SetCurrentRow(row); rowIndices[this[relation.ParentColumns[0]]] = row; } } result = rowIndices[childValues[0]]; if (result != null) { SetCurrentRow(result); return; } } foreach (object row in InternalRows) { SetCurrentRow(row); bool found = true; for (int i = 0; i < columnCount; i++) { if (!this[relation.ParentColumns[i]].Equals(childValues[i])) { found = false; break; } } if (found) { result = row; break; } } if (columnCount == 1) { rowIndices[childValues[0]] = result; } SetCurrentRow(result); }
private void GetChildRows(Relation relation) { // prepare consts object parentRow = relation.ParentDataSource.CurrentRow; int columnsCount = relation.ParentColumns.Length; object[] parentValues = new object[columnsCount]; Column[] childColumns = new Column[columnsCount]; for (int i = 0; i < columnsCount; i++) { parentValues[i] = relation.ParentDataSource[relation.ParentColumns[i]]; childColumns[i] = Columns.FindByAlias(relation.ChildColumns[i]); } if (relation_SortedChildRows == null) { relation_SortedChildRows = new Hashtable(); } // sort the child table at the first run. Use relation columns to sort. SortedList <Indices, ArrayList> sortedChildRows = relation_SortedChildRows[relation] as SortedList <Indices, ArrayList>; if (sortedChildRows == null) { sortedChildRows = new SortedList <Indices, ArrayList>(); relation_SortedChildRows[relation] = sortedChildRows; foreach (object row in InternalRows) { SetCurrentRow(row); object[] values = new object[columnsCount]; for (int i = 0; i < columnsCount; i++) { values[i] = this[childColumns[i]]; } Indices indices = new Indices(values); ArrayList rows = null; int index = sortedChildRows.IndexOfKey(indices); if (index == -1) { rows = new ArrayList(); sortedChildRows.Add(indices, rows); } else { rows = sortedChildRows.Values[index]; } rows.Add(row); } } int indexOfKey = sortedChildRows.IndexOfKey(new Indices(parentValues)); if (indexOfKey != -1) { ArrayList rows = sortedChildRows.Values[indexOfKey]; foreach (object row in rows) { this.rows.Add(row); } } }