660 lines
26 KiB
C#
660 lines
26 KiB
C#
|
//------------------------------------------------------------------------------
|
||
|
// <copyright file="RepeatInfo.cs" company="Microsoft">
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
// </copyright>
|
||
|
//------------------------------------------------------------------------------
|
||
|
|
||
|
namespace System.Web.UI.WebControls {
|
||
|
|
||
|
using System;
|
||
|
using System.Globalization;
|
||
|
using System.Web;
|
||
|
using System.Web.UI;
|
||
|
using System.Web.Util;
|
||
|
|
||
|
/// <devdoc>
|
||
|
/// <para>Defines the information used to render a list of items using
|
||
|
/// a <see cref='System.Web.UI.WebControls.Repeater'/>.</para>
|
||
|
/// </devdoc>
|
||
|
public sealed class RepeatInfo {
|
||
|
|
||
|
private RepeatDirection repeatDirection;
|
||
|
private RepeatLayout repeatLayout;
|
||
|
private int repeatColumns;
|
||
|
private string caption;
|
||
|
private TableCaptionAlign captionAlign;
|
||
|
private bool useAccessibleHeader;
|
||
|
private bool outerTableImplied;
|
||
|
private bool enableLegacyRendering;
|
||
|
|
||
|
|
||
|
/// <devdoc>
|
||
|
/// <para>Initializes a new instance of the <see cref='System.Web.UI.WebControls.RepeatInfo'/> class. This class is not
|
||
|
/// inheritable.</para>
|
||
|
/// </devdoc>
|
||
|
public RepeatInfo() {
|
||
|
repeatDirection = RepeatDirection.Vertical;
|
||
|
repeatLayout = RepeatLayout.Table;
|
||
|
repeatColumns = 0;
|
||
|
outerTableImplied = false;
|
||
|
}
|
||
|
|
||
|
|
||
|
public string Caption {
|
||
|
get {
|
||
|
return (caption == null) ? String.Empty : caption;
|
||
|
}
|
||
|
set {
|
||
|
caption = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
public TableCaptionAlign CaptionAlign {
|
||
|
get {
|
||
|
return captionAlign;
|
||
|
}
|
||
|
set {
|
||
|
if ((value < TableCaptionAlign.NotSet) ||
|
||
|
(value > TableCaptionAlign.Right)) {
|
||
|
throw new ArgumentOutOfRangeException("value");
|
||
|
}
|
||
|
captionAlign = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// DevDiv 33149: A backward compat. switch for Everett rendering
|
||
|
internal bool EnableLegacyRendering {
|
||
|
get {
|
||
|
return enableLegacyRendering;
|
||
|
}
|
||
|
set {
|
||
|
enableLegacyRendering = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private bool IsListLayout {
|
||
|
get {
|
||
|
return
|
||
|
(RepeatLayout == RepeatLayout.UnorderedList) ||
|
||
|
(RepeatLayout == RepeatLayout.OrderedList);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <devdoc>
|
||
|
/// Indicates whether an outer table is implied
|
||
|
/// for the items.
|
||
|
/// </devdoc>
|
||
|
public bool OuterTableImplied {
|
||
|
get {
|
||
|
return outerTableImplied;
|
||
|
}
|
||
|
set {
|
||
|
outerTableImplied = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/// <devdoc>
|
||
|
/// <para> Indicates the column count of items.</para>
|
||
|
/// </devdoc>
|
||
|
public int RepeatColumns {
|
||
|
get {
|
||
|
return repeatColumns;
|
||
|
}
|
||
|
set {
|
||
|
repeatColumns = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/// <devdoc>
|
||
|
/// <para>Indicates the direction of flow of items.</para>
|
||
|
/// </devdoc>
|
||
|
public RepeatDirection RepeatDirection {
|
||
|
get {
|
||
|
return repeatDirection;
|
||
|
}
|
||
|
set {
|
||
|
if (value < RepeatDirection.Horizontal || value > RepeatDirection.Vertical) {
|
||
|
throw new ArgumentOutOfRangeException("value");
|
||
|
}
|
||
|
repeatDirection = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/// <devdoc>
|
||
|
/// Indicates the layout of items.
|
||
|
/// </devdoc>
|
||
|
public RepeatLayout RepeatLayout {
|
||
|
get {
|
||
|
return repeatLayout;
|
||
|
}
|
||
|
set {
|
||
|
EnumerationRangeValidationUtil.ValidateRepeatLayout(value);
|
||
|
repeatLayout = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
public bool UseAccessibleHeader {
|
||
|
get {
|
||
|
return useAccessibleHeader;
|
||
|
}
|
||
|
set {
|
||
|
useAccessibleHeader = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/// <devdoc>
|
||
|
/// </devdoc>
|
||
|
private void RenderHorizontalRepeater(HtmlTextWriter writer, IRepeatInfoUser user, Style controlStyle, WebControl baseControl) {
|
||
|
Debug.Assert(outerTableImplied == false, "Cannot use outer implied table with Horizontal layout");
|
||
|
|
||
|
int itemCount = user.RepeatedItemCount;
|
||
|
|
||
|
int totalColumns = repeatColumns;
|
||
|
int currentColumn = 0;
|
||
|
|
||
|
if (totalColumns == 0) {
|
||
|
// 0 implies a complete horizontal repetition without any
|
||
|
// column count constraints
|
||
|
totalColumns = itemCount;
|
||
|
}
|
||
|
|
||
|
WebControl outerControl = null;
|
||
|
bool tableLayout = false;
|
||
|
|
||
|
switch (repeatLayout) {
|
||
|
case RepeatLayout.Table:
|
||
|
outerControl = new Table();
|
||
|
if (Caption.Length != 0) {
|
||
|
((Table)outerControl).Caption = Caption;
|
||
|
((Table)outerControl).CaptionAlign = CaptionAlign;
|
||
|
}
|
||
|
tableLayout = true;
|
||
|
break;
|
||
|
case RepeatLayout.Flow:
|
||
|
outerControl = new WebControl(HtmlTextWriterTag.Span);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
bool separators = user.HasSeparators;
|
||
|
|
||
|
// use ClientID (and not ID) since we want to render out the fully qualified client id
|
||
|
// even though this outer control will not be parented to the control hierarchy
|
||
|
outerControl.ID = baseControl.ClientID;
|
||
|
|
||
|
outerControl.CopyBaseAttributes(baseControl);
|
||
|
outerControl.ApplyStyle(controlStyle);
|
||
|
outerControl.RenderBeginTag(writer);
|
||
|
|
||
|
if (user.HasHeader) {
|
||
|
if (tableLayout) {
|
||
|
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
|
||
|
|
||
|
// add attributes to render for TD/TH
|
||
|
if ((totalColumns != 1) || separators) {
|
||
|
int columnSpan = totalColumns;
|
||
|
if (separators)
|
||
|
columnSpan += totalColumns;
|
||
|
writer.AddAttribute(HtmlTextWriterAttribute.Colspan, columnSpan.ToString(NumberFormatInfo.InvariantInfo));
|
||
|
}
|
||
|
if (useAccessibleHeader) {
|
||
|
writer.AddAttribute(HtmlTextWriterAttribute.Scope, "col");
|
||
|
}
|
||
|
|
||
|
// add style attributes to render for TD/TH
|
||
|
Style style = user.GetItemStyle(ListItemType.Header, -1);
|
||
|
if (style != null) {
|
||
|
style.AddAttributesToRender(writer);
|
||
|
}
|
||
|
|
||
|
// render begin tag
|
||
|
if (useAccessibleHeader) {
|
||
|
writer.RenderBeginTag(HtmlTextWriterTag.Th);
|
||
|
}
|
||
|
else {
|
||
|
writer.RenderBeginTag(HtmlTextWriterTag.Td);
|
||
|
}
|
||
|
}
|
||
|
user.RenderItem(ListItemType.Header, -1, this, writer);
|
||
|
if (tableLayout) {
|
||
|
// render end tags TD/TH and TR
|
||
|
writer.RenderEndTag();
|
||
|
writer.RenderEndTag();
|
||
|
}
|
||
|
else {
|
||
|
if (totalColumns < itemCount) {
|
||
|
// we have multiple rows, so have a break between the header and first row.
|
||
|
if (EnableLegacyRendering) {
|
||
|
writer.WriteObsoleteBreak();
|
||
|
}
|
||
|
else {
|
||
|
writer.WriteBreak();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (int i = 0; i < itemCount; i++) {
|
||
|
if (tableLayout && (currentColumn == 0)) {
|
||
|
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
|
||
|
}
|
||
|
|
||
|
if (tableLayout) {
|
||
|
// add style attributes to render for TD
|
||
|
Style style = user.GetItemStyle(ListItemType.Item, i);
|
||
|
if (style != null)
|
||
|
style.AddAttributesToRender(writer);
|
||
|
// render begin tag for TD
|
||
|
writer.RenderBeginTag(HtmlTextWriterTag.Td);
|
||
|
}
|
||
|
user.RenderItem(ListItemType.Item, i, this, writer);
|
||
|
if (tableLayout) {
|
||
|
// render end tag for TD
|
||
|
writer.RenderEndTag();
|
||
|
}
|
||
|
if (separators && (i != (itemCount - 1))) {
|
||
|
if (tableLayout) {
|
||
|
Style style = user.GetItemStyle(ListItemType.Separator, i);
|
||
|
if (style != null)
|
||
|
style.AddAttributesToRender(writer);
|
||
|
writer.RenderBeginTag(HtmlTextWriterTag.Td);
|
||
|
}
|
||
|
user.RenderItem(ListItemType.Separator, i, this, writer);
|
||
|
if (tableLayout)
|
||
|
writer.RenderEndTag();
|
||
|
}
|
||
|
|
||
|
currentColumn++;
|
||
|
|
||
|
// on the last line, fill in the rest of the empty spots with <td/>s.
|
||
|
// If there were separators, we need twice as many plus one to accomodate for
|
||
|
// the last item not having a separator after it.
|
||
|
if (tableLayout && i == itemCount - 1) {
|
||
|
int unfilledColumns = totalColumns - currentColumn;
|
||
|
if (separators == true) {
|
||
|
int unfilledColumnsWithSeparators = (unfilledColumns * 2) + 1;
|
||
|
if (unfilledColumnsWithSeparators > unfilledColumns) {
|
||
|
unfilledColumns = unfilledColumnsWithSeparators;
|
||
|
}
|
||
|
}
|
||
|
for (int k = 0; k < unfilledColumns; k++) {
|
||
|
writer.RenderBeginTag(HtmlTextWriterTag.Td);
|
||
|
writer.RenderEndTag();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ((currentColumn == totalColumns) || (i == itemCount - 1)) {
|
||
|
if (tableLayout) {
|
||
|
// End tag for TR
|
||
|
writer.RenderEndTag();
|
||
|
}
|
||
|
else {
|
||
|
// write out the <br> after rows when there are multiple rows
|
||
|
if (totalColumns < itemCount) {
|
||
|
if (EnableLegacyRendering) {
|
||
|
writer.WriteObsoleteBreak();
|
||
|
}
|
||
|
else {
|
||
|
writer.WriteBreak();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
currentColumn = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (user.HasFooter) {
|
||
|
if (tableLayout) {
|
||
|
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
|
||
|
|
||
|
if ((totalColumns != 1) || separators) {
|
||
|
// add attributes to render for TD
|
||
|
int columnSpan = totalColumns;
|
||
|
if (separators)
|
||
|
columnSpan += totalColumns;
|
||
|
writer.AddAttribute(HtmlTextWriterAttribute.Colspan, columnSpan.ToString(NumberFormatInfo.InvariantInfo));
|
||
|
}
|
||
|
// add style attributes to render for TD
|
||
|
Style style = user.GetItemStyle(ListItemType.Footer, -1);
|
||
|
if (style != null)
|
||
|
style.AddAttributesToRender(writer);
|
||
|
// render begin tag for TD
|
||
|
writer.RenderBeginTag(HtmlTextWriterTag.Td);
|
||
|
}
|
||
|
user.RenderItem(ListItemType.Footer, -1, this, writer);
|
||
|
if (tableLayout) {
|
||
|
// render end tag for TR and TD
|
||
|
writer.RenderEndTag();
|
||
|
writer.RenderEndTag();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
outerControl.RenderEndTag(writer);
|
||
|
}
|
||
|
|
||
|
|
||
|
/// <devdoc>
|
||
|
/// <para>Renders the Repeater with the specified
|
||
|
/// information.</para>
|
||
|
/// </devdoc>
|
||
|
public void RenderRepeater(HtmlTextWriter writer, IRepeatInfoUser user, Style controlStyle, WebControl baseControl) {
|
||
|
if (IsListLayout) {
|
||
|
if (user.HasFooter || user.HasHeader || user.HasSeparators) {
|
||
|
throw new InvalidOperationException(SR.GetString(SR.RepeatInfo_ListLayoutDoesNotSupportHeaderFooterSeparator));
|
||
|
}
|
||
|
if (RepeatDirection != RepeatDirection.Vertical) {
|
||
|
throw new InvalidOperationException(SR.GetString(SR.RepeatInfo_ListLayoutOnlySupportsVerticalLayout));
|
||
|
}
|
||
|
if ((RepeatColumns != 0) && (RepeatColumns != 1)) {
|
||
|
throw new InvalidOperationException(SR.GetString(SR.RepeatInfo_ListLayoutDoesNotSupportMultipleColumn));
|
||
|
}
|
||
|
if (OuterTableImplied) {
|
||
|
throw new InvalidOperationException(SR.GetString(SR.RepeatInfo_ListLayoutDoesNotSupportImpliedOuterTable));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (repeatDirection == RepeatDirection.Vertical) {
|
||
|
RenderVerticalRepeater(writer, user, controlStyle, baseControl);
|
||
|
}
|
||
|
else {
|
||
|
RenderHorizontalRepeater(writer, user, controlStyle, baseControl);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <devdoc>
|
||
|
/// </devdoc>
|
||
|
private void RenderVerticalRepeater(HtmlTextWriter writer, IRepeatInfoUser user, Style controlStyle, WebControl baseControl) {
|
||
|
int itemCount = user.RepeatedItemCount;
|
||
|
int totalColumns;
|
||
|
int totalRows;
|
||
|
int filledColumns;
|
||
|
|
||
|
// List Layout Constraint --> Columns = 0 or 1
|
||
|
if ((repeatColumns == 0) || (repeatColumns == 1)) {
|
||
|
// A RepeatColumns of 0 implies a completely vertical repetition in
|
||
|
// a single column. This is same as repeatColumns of 1.
|
||
|
totalColumns = 1;
|
||
|
filledColumns = 1;
|
||
|
totalRows = itemCount;
|
||
|
}
|
||
|
else {
|
||
|
totalColumns = repeatColumns;
|
||
|
totalRows = (int)((itemCount + repeatColumns - 1) / repeatColumns);
|
||
|
|
||
|
if ((totalRows == 0) && (itemCount != 0)) {
|
||
|
// if repeatColumns is a huge number like Int32.MaxValue, then the
|
||
|
// calculation above essentially reduces down to 0
|
||
|
totalRows = 1;
|
||
|
}
|
||
|
|
||
|
filledColumns = itemCount % totalColumns;
|
||
|
if (filledColumns == 0) {
|
||
|
filledColumns = totalColumns;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
WebControl outerControl = null;
|
||
|
bool tableLayout = false;
|
||
|
|
||
|
// List Layout Constraint --> OuterTableImplied = false
|
||
|
// List Layout Constraint --> tableLayout = false
|
||
|
if (!outerTableImplied) {
|
||
|
switch (repeatLayout) {
|
||
|
case RepeatLayout.Table:
|
||
|
outerControl = new Table();
|
||
|
if (Caption.Length != 0) {
|
||
|
((Table)outerControl).Caption = Caption;
|
||
|
((Table)outerControl).CaptionAlign = CaptionAlign;
|
||
|
}
|
||
|
tableLayout = true;
|
||
|
break;
|
||
|
case RepeatLayout.Flow:
|
||
|
outerControl = new WebControl(HtmlTextWriterTag.Span);
|
||
|
break;
|
||
|
case RepeatLayout.UnorderedList:
|
||
|
outerControl = new WebControl(HtmlTextWriterTag.Ul);
|
||
|
break;
|
||
|
case RepeatLayout.OrderedList:
|
||
|
outerControl = new WebControl(HtmlTextWriterTag.Ol);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool separators = user.HasSeparators;
|
||
|
// List Layout Constraint --> separators = false
|
||
|
|
||
|
if (outerControl != null) {
|
||
|
// use ClientID (and not ID) since we want to render out the fully qualified client id
|
||
|
// even though this outer control will not be parented to the control hierarchy
|
||
|
outerControl.ID = baseControl.ClientID;
|
||
|
|
||
|
outerControl.CopyBaseAttributes(baseControl);
|
||
|
outerControl.ApplyStyle(controlStyle);
|
||
|
outerControl.RenderBeginTag(writer);
|
||
|
}
|
||
|
|
||
|
// List Layout Constraint --> HasHeader = false
|
||
|
if (user.HasHeader) {
|
||
|
if (tableLayout) {
|
||
|
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
|
||
|
|
||
|
// add attributes to render for TH
|
||
|
if (totalColumns != 1) {
|
||
|
int columnSpan = totalColumns;
|
||
|
if (separators)
|
||
|
columnSpan += totalColumns;
|
||
|
writer.AddAttribute(HtmlTextWriterAttribute.Colspan, columnSpan.ToString(NumberFormatInfo.InvariantInfo));
|
||
|
}
|
||
|
if (useAccessibleHeader) {
|
||
|
writer.AddAttribute(HtmlTextWriterAttribute.Scope, "col");
|
||
|
}
|
||
|
|
||
|
// add style attributes to render for TD/TH
|
||
|
Style style = user.GetItemStyle(ListItemType.Header, -1);
|
||
|
if (style != null) {
|
||
|
style.AddAttributesToRender(writer);
|
||
|
}
|
||
|
|
||
|
// render begin tag for TD/TH
|
||
|
if (useAccessibleHeader) {
|
||
|
writer.RenderBeginTag(HtmlTextWriterTag.Th);
|
||
|
}
|
||
|
else {
|
||
|
writer.RenderBeginTag(HtmlTextWriterTag.Td);
|
||
|
}
|
||
|
}
|
||
|
user.RenderItem(ListItemType.Header, -1, this, writer);
|
||
|
if (tableLayout) {
|
||
|
// render end tags TD/TH and TR
|
||
|
writer.RenderEndTag();
|
||
|
writer.RenderEndTag();
|
||
|
}
|
||
|
else if (!outerTableImplied) {
|
||
|
if (EnableLegacyRendering) {
|
||
|
writer.WriteObsoleteBreak();
|
||
|
}
|
||
|
else {
|
||
|
writer.WriteBreak();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int itemCounter = 0;
|
||
|
|
||
|
for (int currentRow = 0; currentRow < totalRows; currentRow++) {
|
||
|
// List Layout Constraint --> tableLayout = false
|
||
|
if (tableLayout) {
|
||
|
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
|
||
|
}
|
||
|
|
||
|
int itemIndex = currentRow;
|
||
|
|
||
|
for (int currentCol = 0; currentCol < totalColumns; currentCol++) {
|
||
|
if (itemCounter >= itemCount) {
|
||
|
// done rendering all items, so break out of the loop now...
|
||
|
// we might end up here, in unfilled columns attempting to re-render items that
|
||
|
// have already been rendered on the next column in a prior row.
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (currentCol != 0) {
|
||
|
itemIndex += totalRows;
|
||
|
|
||
|
// if the previous column (currentColumn - 1) was not a filled column, i.e.,
|
||
|
// it had one less item (the maximum possible), then subtract 1 from the item index.
|
||
|
if ((currentCol - 1) >= filledColumns) {
|
||
|
itemIndex--;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
if (itemIndex >= itemCount)
|
||
|
continue;
|
||
|
|
||
|
itemCounter++;
|
||
|
|
||
|
// List Layout Constraint --> tableLayout = false
|
||
|
if (tableLayout) {
|
||
|
// add style attributes to render for TD
|
||
|
Style style = user.GetItemStyle(ListItemType.Item, itemIndex);
|
||
|
if (style != null)
|
||
|
style.AddAttributesToRender(writer);
|
||
|
// render begin tag for TD
|
||
|
writer.RenderBeginTag(HtmlTextWriterTag.Td);
|
||
|
}
|
||
|
|
||
|
if (IsListLayout) {
|
||
|
writer.RenderBeginTag(HtmlTextWriterTag.Li);
|
||
|
}
|
||
|
|
||
|
user.RenderItem(ListItemType.Item, itemIndex, this, writer);
|
||
|
|
||
|
if (IsListLayout) {
|
||
|
writer.RenderEndTag();
|
||
|
writer.WriteLine();
|
||
|
}
|
||
|
|
||
|
// List Layout Constraint --> tableLayout = false
|
||
|
if (tableLayout) {
|
||
|
// render end tag for TD
|
||
|
writer.RenderEndTag();
|
||
|
}
|
||
|
|
||
|
// List Layout Constraint --> separators = false
|
||
|
if (separators) {
|
||
|
if (itemIndex != (itemCount - 1)) {
|
||
|
if (totalColumns == 1) {
|
||
|
if (tableLayout) {
|
||
|
writer.RenderEndTag();
|
||
|
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
|
||
|
}
|
||
|
else {
|
||
|
if (!outerTableImplied) {
|
||
|
if (EnableLegacyRendering) {
|
||
|
writer.WriteObsoleteBreak();
|
||
|
}
|
||
|
else {
|
||
|
writer.WriteBreak();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (tableLayout) {
|
||
|
Style style = user.GetItemStyle(ListItemType.Separator, itemIndex);
|
||
|
if (style != null)
|
||
|
style.AddAttributesToRender(writer);
|
||
|
writer.RenderBeginTag(HtmlTextWriterTag.Td);
|
||
|
}
|
||
|
if (itemIndex < itemCount)
|
||
|
user.RenderItem(ListItemType.Separator, itemIndex, this, writer);
|
||
|
if (tableLayout)
|
||
|
writer.RenderEndTag();
|
||
|
}
|
||
|
else {
|
||
|
// if we're on the last filled line and separators are specified, add another <td/>
|
||
|
// to accomodate for the lack of a separator on the last item. If there's only one
|
||
|
// column, though, separators will get their own row anyways.
|
||
|
if (tableLayout && totalColumns > 1) {
|
||
|
writer.RenderBeginTag(HtmlTextWriterTag.Td);
|
||
|
writer.RenderEndTag();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// on the last line, fill in the remaining empty slots with <td/>s. We need twice as many
|
||
|
// if there were separators.
|
||
|
// List Layout Constraint --> tableLayout = false
|
||
|
if (tableLayout) {
|
||
|
if (currentRow == totalRows - 1) {
|
||
|
int unfilledColumns = totalColumns - filledColumns;
|
||
|
if (separators) {
|
||
|
int unfilledColumnsWithSeparators = unfilledColumns * 2;
|
||
|
if (unfilledColumnsWithSeparators >= unfilledColumns) {
|
||
|
unfilledColumns = unfilledColumnsWithSeparators;
|
||
|
}
|
||
|
}
|
||
|
if (unfilledColumns != 0) {
|
||
|
for (int i = 0; i < unfilledColumns; i++) {
|
||
|
writer.RenderBeginTag(HtmlTextWriterTag.Td);
|
||
|
writer.RenderEndTag();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
writer.RenderEndTag();
|
||
|
}
|
||
|
else {
|
||
|
if (((currentRow != totalRows - 1) || user.HasFooter) &&
|
||
|
(!outerTableImplied) && (!IsListLayout)) {
|
||
|
|
||
|
if (EnableLegacyRendering) {
|
||
|
writer.WriteObsoleteBreak();
|
||
|
}
|
||
|
else {
|
||
|
writer.WriteBreak();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// List Layout Constraint --> HasFooter = false
|
||
|
if (user.HasFooter) {
|
||
|
if (tableLayout) {
|
||
|
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
|
||
|
// add attributes to render for TD
|
||
|
if (totalColumns != 1) {
|
||
|
int columnSpan = totalColumns;
|
||
|
if (separators)
|
||
|
columnSpan += totalColumns;
|
||
|
writer.AddAttribute(HtmlTextWriterAttribute.Colspan, columnSpan.ToString(NumberFormatInfo.InvariantInfo));
|
||
|
}
|
||
|
// add style attributes to render for TD
|
||
|
Style style = user.GetItemStyle(ListItemType.Footer, -1);
|
||
|
if (style != null)
|
||
|
style.AddAttributesToRender(writer);
|
||
|
// render begin tag for TD
|
||
|
writer.RenderBeginTag(HtmlTextWriterTag.Td);
|
||
|
}
|
||
|
user.RenderItem(ListItemType.Footer, -1, this, writer);
|
||
|
if (tableLayout) {
|
||
|
// render end tag for TR and TD
|
||
|
writer.RenderEndTag();
|
||
|
writer.RenderEndTag();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (outerControl != null)
|
||
|
outerControl.RenderEndTag(writer);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|