public override void ResolveSublayoutReferences() { // Call the base class implementation to resolve any sublayouts // that were declared statically in the design file base.ResolveSublayoutReferences(); // Create dynamic sublayouts based on our source reference. These // new sublayouts will be resolved as soon as we create them // because we'll be passing resolved references to them. List <Reference> items = new List <Reference>(); switch (_sourcePath.TargetType) { case ContentSourceType.Checkbox: case ContentSourceType.RadioButton: case ContentSourceType.TextEntry: case ContentSourceType.Calculation: case ContentSourceType.Section: items.Add(_sourceObject); break; case ContentSourceType.MultiSelect: case ContentSourceType.SingleSelect: case ContentSourceType.CalculationList: // Include all the items in the source list List <Reference> children = _generator.Resolver.GetChildren(_sourceObject); items.AddRange(children); break; } // We want the dynamic sublayouts based on our source reference to appear // first in the list, before static layouts defined in the design file. // The static layouts have already been added by the call to the base // class implementation of this method (which must be called before we // do our own stuff here, because it clears _subLayouts) and so we want // to start inserting the dynamic layouts at index zero. To preserve the // internal order of those dynamic layouts, we increment the insert // index for each one. int insertIndex = 0; foreach (Reference item in items) { bool satisfies = _conditions.SatisfiesContentConditions(item); if (!satisfies) { continue; } TextLayout layout = new TextLayout(item, _style.ItemStyle, _generator, _trackingInfo.LineNumber, _trackingInfo.LinePosition); InsertSubLayout(insertIndex++, layout); } //TODO: For calculations, which have complex structure, a complex rendition //comprised of any of the calculation's parts - caption, value and unit of //measure - all in a single list item. For example, "price : $10.00" or //"size = 30sq.m.". I think this is easy enough to do in a text layout, //and we could embed a text layout in the list, but then how would we repeat //the text layout for all calculations that the source reference resolves to? //Do we need to add a "pattern" attribute to ListLayout? Something like // <ListLayout source="CalculationList:1234[...]" pattern="!Caption = !Value!UnitOfMeasure"> //See Jira ticket DEMON-268. // Merge sublists into this list MergeSubLists(); // Pass on our static conditions to our items so that they can // apply them when they load their content foreach (Layout layout in _subLayouts) { layout.AddConditions(_conditions); } // Wrap our sublayouts in list items List <Layout> wrapped = WrapSublayouts(_subLayouts); // Set ourself as the container on each of the wrappers. Creating the // wrappers has automatically made each wrapper the container of its // content layout, replacing us. Making ourself the container of the // wrappers keeps the container hierarchy intact. The hierarchy must // be maintained so that reference resolution can have correct context. _subLayouts.Clear(); foreach (Layout sublayout in wrapped) { AddSubLayout(sublayout); } // Prepare our empty text in case we need to use it later. Even if we have // some items now, after applying conditions we may be left with none, // in which case we'll need our empty text. if (!string.IsNullOrWhiteSpace(_emptyText)) { ListStyle style = _emptyStyle ?? _style; _whenEmpty = new TextLayout(_emptyText, style.ItemStyle, _generator, _trackingInfo.LineNumber, _trackingInfo.LinePosition); List <Layout> unwrapped = new List <Layout>(); unwrapped.Add(_whenEmpty); wrapped = WrapSublayouts(unwrapped); _whenEmpty = wrapped[0]; } // Use our empty layout right away if we're empty if ((_subLayouts.Count == 0) && (_whenEmpty != null)) { AddSubLayout(_whenEmpty); } }