Пример #1
0
        protected override void loadData()
        {
            var updateRegionSet = new UpdateRegionSet();

            EwfUiStatics.SetPageActions(
                new ActionButtonSetup(
                    "Remove Last Group",
                    new PostBackButton(
                        PostBack.CreateIntermediate(
                            updateRegionSet.ToCollection(),
                            id: "removeLastGroup",
                            firstModificationMethod: () => {
                if (info.GroupCount <= 0)
                {
                    throw new DataModificationException("No groups to remove.");
                }
                parametersModification.GroupCount -= 1;
            }))));

            place.Controls.Add(
                EwfTable.CreateWithItemGroups(
                    Enumerable.Range(1, info.GroupCount).Select(getItemGroup),
                    defaultItemLimit: DataRowLimit.Fifty,
                    caption: "Caption",
                    subCaption: "Sub caption",
                    fields:
                    new[]
                    { new EwfTableField(size: Unit.Percentage(1), toolTip: "First column!"), new EwfTableField(size: Unit.Percentage(2), toolTip: "Second column!") },
                    headItems: new EwfTableItem("First Column", "Second Column").ToCollection(),
                    tailUpdateRegions: new TailUpdateRegion(updateRegionSet.ToCollection(), 1).ToCollection()));
        }
 private FlowComponent getCommentFooter(CommentsTableRetrieval.Row comment, UsersTableRetrieval.Row author, UpdateRegionSet deleteUpdateRegions) =>
 new GenericFlowContainer(
     new GenericFlowContainer(
         new GenericPhrasingContainer(
             new EwfHyperlink(
                 Profile.GetInfo(comment.AuthorId),
                 new ImageHyperlinkStyle(
                     new ExternalResource(
                         author.ProfilePictureUrl.Any() ? author.ProfilePictureUrl : "https://static.productionready.io/images/smiley-cyrus.jpg"),
                     "")).ToCollection())
         .Append(
             new GenericPhrasingContainer(
                 new EwfHyperlink(Profile.GetInfo(comment.AuthorId), new StandardHyperlinkStyle(author.Username)).ToCollection()))
         .Append(new GenericPhrasingContainer(comment.CreationDateAndTime.ToDayMonthYearString(false).ToComponents()))
         .Materialize()).Concat <FlowComponent>(
         comment.AuthorId == AppTools.User?.UserId
                                                 ? new EwfButton(
             new StandardButtonStyle("Delete", icon: new ActionComponentIcon(new FontAwesomeIcon("fa-trash"))),
             behavior: new PostBackBehavior(
                 postBack: PostBack.CreateIntermediate(
                     deleteUpdateRegions.ToCollection(),
                     id: PostBack.GetCompositeId("delete", comment.CommentId.ToString()),
                     modificationMethod: () => CommentsModification.DeleteRows(new CommentsTableEqualityConditions.CommentId(comment.CommentId)))))
         .ToCollection()
                                                 : Enumerable.Empty <PhrasingComponent>())
     .Materialize());
        private IEnumerable <Control> getIdListRegionBlocks()
        {
            var rs = new UpdateRegionSet();

            yield return
                (new ControlLine(
                     new PostBackButton(
                         PostBack.CreateIntermediate(
                             rs.ToSingleElementArray(),
                             DataUpdate,
                             id: "idAdd",
                             firstModificationMethod:
                             () =>
                             parametersModification.ItemIds =
                                 (parametersModification.ItemIds.Any() ? parametersModification.ItemIds.Min() - 1 : 0).ToSingleElementArray().Concat(parametersModification.ItemIds)),
                         new ButtonActionControlStyle("Add Item"),
                         usesSubmitBehavior: false)));

            var stack = ControlStack.Create(
                true,
                itemInsertionUpdateRegions:
                new ItemInsertionUpdateRegion(rs, () => parametersModification.ItemIds.First().ToString().ToSingleElementArray()).ToSingleElementArray());

            foreach (var i in info.ItemIds)
            {
                stack.AddItem(getIdItem(i));
            }

            yield return(new Box("Control List With ID Items", stack.ToSingleElementArray()));
        }
        private IEnumerable <Control> getBasicRegionBlocks()
        {
            var rs = new UpdateRegionSet();
            var pb = PostBack.CreateIntermediate(rs.ToSingleElementArray(), DataUpdate, id: "basic");

            yield return(new Paragraph(new PostBackButton(pb, new ButtonActionControlStyle("Toggle Basic Region Below"), usesSubmitBehavior: false)));

            var regionControls    = new List <Control>();
            var dynamicFieldValue = new DataValue <string>();

            if (info.Toggled)
            {
                regionControls.Add(
                    FormItem.Create(
                        "Dynamic Field",
                        new EwfTextBox("This was just added!"),
                        validationGetter: control => new EwfValidation((pbv, validator) => dynamicFieldValue.Value = control.GetPostBackValue(pbv), pb)).ToControl());
            }
            else
            {
                regionControls.Add(new Paragraph("Nothing here yet."));
            }
            yield return(new NamingPlaceholder(new Box("Basic Update Region", regionControls).ToSingleElementArray(), updateRegionSet: rs));

            pb.AddModificationMethod(() => parametersModification.Toggled = !parametersModification.Toggled);
            pb.AddModificationMethod(
                () =>
                AddStatusMessage(StatusMessageType.Info, info.Toggled ? "Dynamic field value was '{0}'.".FormatWith(dynamicFieldValue.Value) : "Dynamic field added."));
        }
        private IReadOnlyCollection <FlowComponent> getNewCommentComponents(UpdateRegionSet createUpdateRegions)
        {
            if (AppTools.User == null)
            {
                return(new Paragraph(
                           new EwfHyperlink(
                               EnterpriseWebLibrary.EnterpriseWebFramework.UserManagement.Pages.LogIn.GetInfo(Home.GetInfo().GetUrl()),
                               new StandardHyperlinkStyle("Sign in")).Concat(" or ".ToComponents())
                           .Append(new EwfHyperlink(User.GetInfo(), new StandardHyperlinkStyle("sign up")))
                           .Concat(" to add comments on this article.".ToComponents())
                           .Materialize()).ToCollection());
            }

            commentMod = getCommentMod();
            return(FormState.ExecuteWithDataModificationsAndDefaultAction(
                       PostBack.CreateIntermediate(
                           createUpdateRegions.ToCollection(),
                           id: "comment",
                           modificationMethod: () => {
                commentMod.CommentId = MainSequence.GetNextValue();
                commentMod.Execute();
            })
                       .ToCollection(),
                       () => new FlowIdContainer(
                           commentMod.GetBodyTextTextControlFormItem(
                               false,
                               label: Enumerable.Empty <PhrasingComponent>().Materialize(),
                               controlSetup: TextControlSetup.Create(numberOfRows: 3, placeholder: "Write a comment..."),
                               value: "")
                           .ToComponentCollection()
                           .Append(new EwfButton(new StandardButtonStyle("Post Comment"))),
                           updateRegionSets: createUpdateRegions.ToCollection()).ToCollection()));
        }
        private IEnumerable <Control> getNonIdListRegionBlocks()
        {
            var addRs    = new UpdateRegionSet();
            var removeRs = new UpdateRegionSet();

            yield return
                (new ControlLine(
                     new PostBackButton(
                         PostBack.CreateIntermediate(
                             addRs.ToSingleElementArray(),
                             DataUpdate,
                             id: "nonIdAdd",
                             firstModificationMethod: () => parametersModification.NonIdItemStates = parametersModification.NonIdItemStates.Concat(new[] { 0, 0 })),
                         new ButtonActionControlStyle("Add Two Items"),
                         usesSubmitBehavior: false),
                     new PostBackButton(
                         PostBack.CreateIntermediate(
                             removeRs.ToSingleElementArray(),
                             DataUpdate,
                             id: "nonIdRemove",
                             firstModificationMethod:
                             () => parametersModification.NonIdItemStates = parametersModification.NonIdItemStates.Take(parametersModification.NonIdItemStates.Count() - 2)),
                         new ButtonActionControlStyle("Remove Two Items"),
                         usesSubmitBehavior: false)));

            var stack = ControlStack.Create(true, tailUpdateRegions: new[] { new TailUpdateRegion(addRs, 0), new TailUpdateRegion(removeRs, 2) });

            for (var i = 0; i < info.NonIdItemStates.Count(); i += 1)
            {
                stack.AddItem(getNonIdItem(i));
            }

            yield return(new Box("Control List With Non-ID Items", stack.ToSingleElementArray()));
        }
Пример #7
0
        private ComponentListItem getNonIdItem(int i)
        {
            var rs = new UpdateRegionSet();

            var items = new List <ComponentListItem>();

            if (info.NonIdItemStates.ElementAt(i) == 1)
            {
                items.Add(new TextControl("Item {0}".FormatWith(i), true).ToFormItem().ToListItem());
            }
            else
            {
                items.Add("Item {0}".FormatWith(i).ToComponents().ToComponentListItem());
            }
            items.Add(
                new EwfButton(
                    new StandardButtonStyle("Toggle", buttonSize: ButtonSize.ShrinkWrap),
                    behavior: new PostBackBehavior(
                        postBack: PostBack.CreateIntermediate(
                            rs.ToCollection(),
                            id: PostBack.GetCompositeId("nonId", i.ToString()),
                            firstModificationMethod: () => parametersModification.NonIdItemStates =
                                parametersModification.NonIdItemStates.Select(
                                    (state, index) => index == i ? (state + 1) % 2 : state))))
                .ToCollection()
                .ToComponentListItem());

            return(new StackList(items).ToCollection().ToComponentListItem(updateRegionSets: rs.ToCollection()));
        }
Пример #8
0
        private IReadOnlyCollection <FlowComponent> getIdListRegionComponents()
        {
            var components = new List <FlowComponent>();

            var rs = new UpdateRegionSet();

            components.Add(
                new LineList(
                    new EwfButton(
                        new StandardButtonStyle("Add Item"),
                        behavior: new PostBackBehavior(
                            postBack: PostBack.CreateIntermediate(
                                rs.ToCollection(),
                                id: "idAdd",
                                firstModificationMethod: () =>
                                parametersModification.ItemIds = (parametersModification.ItemIds.Any() ? parametersModification.ItemIds.Min() - 1 : 0).ToCollection()
                                                                 .Concat(parametersModification.ItemIds)))).ToCollection()
                    .ToComponentListItem()
                    .ToLineListItemCollection()));

            var stack = new StackList(
                info.ItemIds.Select(getIdItem),
                setup: new ComponentListSetup(
                    itemInsertionUpdateRegions: new ItemInsertionUpdateRegion(rs.ToCollection(), () => parametersModification.ItemIds.First().ToString().ToCollection())
                    .ToCollection()));

            components.Add(new Section("Control List With ID Items", stack.ToCollection(), style: SectionStyle.Box));
            return(components);
        }
Пример #9
0
        private EwfTableItemGroup getItemGroup(int groupNumber)
        {
            var updateRegionSet = new UpdateRegionSet();

            return
                (new EwfTableItemGroup(
                     () =>
                     new EwfTableItemGroupRemainingData(
                         new PlaceHolder().AddControlsReturnThis("Group {0}".FormatWith(groupNumber).ToComponents().GetControls()),
                         groupHeadClickScript:
                         ClickScript.CreatePostBackScript(
                             PostBack.CreateIntermediate(
                                 null,
                                 id: "group{0}".FormatWith(groupNumber),
                                 firstModificationMethod: () => AddStatusMessage(StatusMessageType.Info, "You clicked group {0}.".FormatWith(groupNumber)))),
                         tailUpdateRegions: groupNumber == 1 ? new TailUpdateRegion(updateRegionSet.ToCollection(), 1).ToCollection() : null),
                     groupNumber == 1
                                                ? getItems(info.FirstGroupItemCount)
                     .Concat(
                         new Func <EwfTableItem>(
                             () =>
                             new EwfTableItem(
                                 new PostBackButton(
                                     new ButtonActionControlStyle("Add Row"),
                                     usesSubmitBehavior: false,
                                     postBack:
                                     PostBack.CreateIntermediate(
                                         updateRegionSet.ToCollection(),
                                         id: "addRow",
                                         firstModificationMethod: () => parametersModification.FirstGroupItemCount += 1)).ToCell(new TableCellSetup(fieldSpan: 2)))).ToCollection())
                                                : getItems(250)));
        }
Пример #10
0
        private EwfTableItemGroup getItemGroup(int groupNumber)
        {
            var updateRegionSet = new UpdateRegionSet();

            return(EwfTableItemGroup.Create(
                       () => new EwfTableItemGroupRemainingData(
                           "Group {0}".FormatWith(groupNumber).ToComponents(),
                           groupActions: groupNumber == 2
                                                              ? new ButtonSetup(
                               "Action 1",
                               behavior: new PostBackBehavior(
                                   postBack: PostBack.CreateIntermediate(
                                       null,
                                       id: PostBack.GetCompositeId(groupNumber.ToString(), "action1"),
                                       modificationMethod: () => AddStatusMessage(StatusMessageType.Info, "Action 1")))).Append(
                               new ButtonSetup(
                                   "Action 2",
                                   behavior: new PostBackBehavior(
                                       postBack: PostBack.CreateIntermediate(
                                           null,
                                           id: PostBack.GetCompositeId(groupNumber.ToString(), "action2"),
                                           modificationMethod: () => AddStatusMessage(StatusMessageType.Info, "Action 2")))))
                           .Materialize()
                                                              : null,
                           groupHeadActivationBehavior: ElementActivationBehavior.CreateButton(
                               new PostBackBehavior(
                                   postBack: PostBack.CreateIntermediate(
                                       null,
                                       id: "group{0}".FormatWith(groupNumber),
                                       modificationMethod: () => AddStatusMessage(StatusMessageType.Info, "You clicked group {0}.".FormatWith(groupNumber))))),
                           tailUpdateRegions: groupNumber == 1 ? new TailUpdateRegion(updateRegionSet.ToCollection(), 1).ToCollection() : null),
                       groupNumber == 1
                                        ? getItems(FirstGroupItemCount, true)
                       .Concat(
                           new Func <EwfTableItem>(
                               () => EwfTableItem.Create(
                                   new EwfButton(
                                       new StandardButtonStyle("Add Row"),
                                       behavior: new PostBackBehavior(
                                           postBack: PostBack.CreateIntermediate(
                                               updateRegionSet.ToCollection(),
                                               id: "addRow",
                                               modificationMethod: () => parametersModification.FirstGroupItemCount += 1))).ToCollection()
                                   .ToCell(),
                                   "".ToCell())).ToCollection())
                                        : getItems(250, false),
                       selectedItemActions: groupNumber == 1
                                                             ? SelectedItemAction.CreateWithIntermediatePostBackBehavior <int>(
                           "Echo group IDs",
                           null,
                           ids => AddStatusMessage(
                               StatusMessageType.Info,
                               StringTools.GetEnglishListPhrase(ids.Select(i => i.ToString()), true)))
                       .ToCollection()
                                                             : Enumerable.Empty <SelectedItemAction <int> >().Materialize()));
        }
Пример #11
0
 private IReadOnlyCollection <PhrasingComponent> getTagListComponents(DataValue <IReadOnlyCollection <int> > tagIds, UpdateRegionSet removeUpdateRegions) =>
 tagIds.Value.Select(
     tagId => new GenericPhrasingContainer(
         new EwfButton(
             new CustomButtonStyle(children: new FontAwesomeIcon("fa-times").ToCollection()),
             behavior: new PostBackBehavior(
                 postBack: PostBack.CreateIntermediate(
                     removeUpdateRegions.ToCollection(),
                     id: PostBack.GetCompositeId("removeTag", tagId.ToString()),
                     modificationMethod: () => tagIds.Value = tagIds.Value.Where(i => i != tagId).Materialize())))
         .Concat(" {0}".FormatWith(TagsTableRetrieval.GetRowMatchingId(tagId).TagName).ToComponents())
         .Materialize(),
         classes: ElementClasses.EditorTag))
 .Materialize();
Пример #12
0
        private IReadOnlyCollection <PhrasingComponent> getGlobalTabComponents(DataValue <string> filter, UpdateRegionSet resultUpdateRegions)
        {
            const string label = "Global Feed";

            return(filter.Value != "user" && !filter.Value.StartsWith("tag")
                                       ? label.ToComponents()
                                       : new EwfButton(
                       new StandardButtonStyle(label),
                       behavior: new PostBackBehavior(
                           postBack: PostBack.CreateIntermediate(
                               resultUpdateRegions.ToCollection(),
                               id: "global",
                               modificationMethod: () => filter.Value = "global"))).ToCollection());
        }
        private ControlListItem getIdItem(int id)
        {
            var rs = new UpdateRegionSet();
            var pb = PostBack.CreateIntermediate(rs.ToSingleElementArray(), DataUpdate, id: PostBack.GetCompositeId("id", id.ToString()));

            var itemStack = ControlStack.Create(true);

            itemStack.AddControls(new EwfTextBox("ID {0}".FormatWith(id)));
            itemStack.AddControls(
                new PostBackButton(pb, new ButtonActionControlStyle("Remove", buttonSize: ButtonActionControlStyle.ButtonSize.ShrinkWrap), usesSubmitBehavior: false));

            pb.AddModificationMethod(() => parametersModification.ItemIds = parametersModification.ItemIds.Where(i => i != id).ToArray());

            return(new ControlListItem(itemStack.ToSingleElementArray(), id.ToString(), removalUpdateRegionSet: rs));
        }
Пример #14
0
        private IReadOnlyCollection <PhrasingComponent> getUserTabComponents(DataValue <string> filter, UpdateRegionSet resultUpdateRegions)
        {
            const string label = "Your Feed";

            return(AppTools.User != null
                                       ? filter.Value == "user" ? label.ToComponents() :
                   new EwfButton(
                       new StandardButtonStyle(label),
                       behavior: new PostBackBehavior(
                           postBack: PostBack.CreateIntermediate(
                               resultUpdateRegions.ToCollection(),
                               id: "user",
                               modificationMethod: () => filter.Value = "user"))).ToCollection()
                                       : Enumerable.Empty <PhrasingComponent>().Materialize());
        }
Пример #15
0
 private IReadOnlyCollection <Func <string, FormItem> > getControls() =>
 new[]
 {
     getCheckbox("Standard", null), id => {
         var pb = PostBack.CreateIntermediate(null, id: id);
         return(FormState.ExecuteWithDataModificationsAndDefaultAction(
                    FormState.Current.DataModifications.Append(pb),
                    () => getCheckbox("Separate value-changed action", CheckboxSetup.Create(valueChangedAction: new PostBackFormAction(pb)))(id)));
     },
     new Func <Func <string, FormItem> >(
         () => {
         var pmv = new PageModificationValue <bool>();
         return(getCheckbox("Page modification", CheckboxSetup.Create(pageModificationValue: pmv), pageModificationValue: pmv));
     })(),
     getCheckbox("Read-only", CheckboxSetup.CreateReadOnly()), getFlowCheckbox("Flow", null),
     getFlowCheckbox("Flow with highlighting", FlowCheckboxSetup.Create(highlightedWhenChecked: true)),
     getFlowCheckbox(
         "Flow with nested content",
         FlowCheckboxSetup.Create(
             nestedContentGetter: () => new Paragraph(
                 "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin id vestibulum neque. Suspendisse vel sem ac nunc condimentum tempus eget quis nunc. Morbi mattis elementum cursus. Integer eros mi, porttitor vitae orci eget, facilisis pretium diam. Aenean et nisi leo. Aenean nibh ligula, suscipit sit amet nulla ac, faucibus suscipit ipsum. Nunc quis faucibus ex."
                 .ToComponents()).ToCollection())),
     getFlowCheckbox(
         "Flow with nested content always displayed",
         FlowCheckboxSetup.Create(
             nestedContentGetter: () => new Paragraph(
                 "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vel diam quis felis accumsan tempus. Nunc hendrerit mi in hendrerit finibus. Nullam aliquet pharetra mauris ac vehicula. Quisque vehicula imperdiet pulvinar. Morbi ullamcorper est non arcu suscipit, quis interdum ex egestas. Sed vel risus vitae nisl scelerisque pretium. Aliquam vel pretium orci, eu scelerisque felis. Morbi ac auctor lacus, sit amet congue nunc."
                 .ToComponents()).ToCollection(),
             nestedContentAlwaysDisplayed: true)),
     getRadioGroup("Radio group", null),
     getRadioGroup("Radio group with no selection", null, noSelection: true),
     getRadioGroup("Radio group with single button", null, singleButton: true), id => {
         var pb = PostBack.CreateIntermediate(null, id: id);
         return(FormState.ExecuteWithDataModificationsAndDefaultAction(
                    FormState.Current.DataModifications.Append(pb),
                    () => getRadioGroup("Radio group with separate selection-changed action", null, selectionChangedAction: new PostBackFormAction(pb))(id)));
     },
     new Func <Func <string, FormItem> >(
         () => {
         var pmv = new PageModificationValue <bool>();
         return(getRadioGroup("Radio group with page modification", RadioButtonSetup.Create(pageModificationValue: pmv), pageModificationValue: pmv));
     })(),
     getRadioGroup("Radio group with read-only button", RadioButtonSetup.CreateReadOnly())
 };
Пример #16
0
        protected override PageContent getContent()
        {
            var content = new UiPageContent();

            var updateRegionSet = new UpdateRegionSet();

            content.Add(
                EwfTable.Create(
                    caption: "Caption",
                    subCaption: "Sub caption",
                    allowExportToExcel: true,
                    tableActions: new ButtonSetup(
                        "Remove Last Group",
                        behavior: new PostBackBehavior(
                            postBack: PostBack.CreateIntermediate(
                                updateRegionSet.ToCollection(),
                                id: "removeLastGroup",
                                modificationMethod: () => {
                if (GroupCount <= 0)
                {
                    throw new DataModificationException("No groups to remove.");
                }
                parametersModification.GroupCount -= 1;
            }))).ToCollection(),
                    selectedItemActions: SelectedItemAction
                    .CreateWithIntermediatePostBackBehavior <int>(
                        "Echo IDs",
                        null,
                        ids => AddStatusMessage(StatusMessageType.Info, StringTools.GetEnglishListPhrase(ids.Select(i => i.ToString()), true)))
                    .Append(
                        SelectedItemAction.CreateWithIntermediatePostBackBehavior <int>(
                            "With confirmation",
                            null,
                            ids => AddStatusMessage(StatusMessageType.Info, StringTools.GetEnglishListPhrase(ids.Select(i => i.ToString()), true)),
                            confirmationDialogContent: "Are you sure?".ToComponents()))
                    .Materialize(),
                    fields: new[] { new EwfTableField(size: 1.ToPercentage()), new EwfTableField(size: 2.ToPercentage()) },
                    headItems: EwfTableItem.Create("First Column".ToCell(), "Second Column".ToCell()).ToCollection(),
                    defaultItemLimit: DataRowLimit.Fifty,
                    tailUpdateRegions: new TailUpdateRegion(updateRegionSet.ToCollection(), 1).ToCollection())
                .AddItemGroups(Enumerable.Range(1, GroupCount).Select(getItemGroup).Materialize()));

            return(content);
        }
        private ComponentListItem getIdItem(int id)
        {
            var rs = new UpdateRegionSet();

            var items = new List <ComponentListItem>();

            items.Add(new TextControl("ID {0}".FormatWith(id), true).ToFormItem().ToListItem());
            items.Add(
                new EwfButton(
                    new StandardButtonStyle("Remove", buttonSize: ButtonSize.ShrinkWrap),
                    behavior: new PostBackBehavior(
                        postBack: PostBack.CreateIntermediate(
                            rs.ToCollection(),
                            id: PostBack.GetCompositeId("id", id.ToString()),
                            modificationMethod: () => parametersModification.ItemIds = parametersModification.ItemIds.Where(i => i != id).ToArray()))).ToCollection()
                .ToComponentListItem());

            return(new StackList(items).ToCollection().ToComponentListItem(id.ToString(), removalUpdateRegionSets: rs.ToCollection()));
        }
Пример #18
0
        private ComponentListItem getItemLimitButtonItem(DataRowLimit itemLimit, UpdateRegionSet updateRegionSet)
        {
            var text = itemLimit == DataRowLimit.Unlimited ? "All" : ((int)itemLimit).ToString();

            if (itemLimit == (DataRowLimit)CurrentItemLimit)
            {
                return(text.ToComponents().ToComponentListItem());
            }
            return
                (new EwfButton(
                     new StandardButtonStyle(text, buttonSize: ButtonSize.ShrinkWrap),
                     behavior:
                     new PostBackBehavior(
                         postBack:
                         PostBack.CreateIntermediate(
                             updateRegionSet.ToCollection(),
                             id: PostBack.GetCompositeId(postBackIdBase, itemLimit.ToString()),
                             firstModificationMethod: () => EwfPage.Instance.PageState.SetValue(this, itemLimitPageStateKey, (int)itemLimit)))).ToCollection()
                 .ToComponentListItem());
        }
Пример #19
0
        private Control getItemLimitButton(DataRowLimit itemLimit, UpdateRegionSet updateRegionSet)
        {
            var text = itemLimit == DataRowLimit.Unlimited ? "All" : ((int)itemLimit).ToString();

            if (itemLimit == (DataRowLimit)CurrentItemLimit)
            {
                return(text.GetLiteralControl());
            }
            var validationDm = EwfPage.Instance.DataUpdate;             // This is a hack, but should be easily corrected when EnduraCode goal 768 is done.

            return
                (new PostBackButton(
                     PostBack.CreateIntermediate(
                         updateRegionSet.ToSingleElementArray(),
                         validationDm,
                         id: PostBack.GetCompositeId(postBackIdBase, itemLimit.ToString()),
                         firstModificationMethod: () => EwfPage.Instance.PageState.SetValue(this, itemLimitPageStateKey, (int)itemLimit)),
                     new TextActionControlStyle(text),
                     usesSubmitBehavior: false));
        }
Пример #20
0
 private IReadOnlyCollection <Func <string, FormItem> > getControls() =>
 new[]
 {
     get("Standard", null), get("Max length 25", null, maxLength: 25), get("Placeholder", TextControlSetup.Create(placeholder: "Type here")),
     get("Name auto-fill", TextControlSetup.Create(autoFillTokens: "name")),
     get("Auto-complete", TextControlSetup.CreateAutoComplete(TestService.GetInfo())),
     get("Spell-checking disabled", TextControlSetup.Create(checksSpellingAndGrammar: false)),
     get("Spell-checking enabled", TextControlSetup.Create(checksSpellingAndGrammar: true)), id => {
         var pb = PostBack.CreateIntermediate(null, id: id);
         return(FormState.ExecuteWithDataModificationsAndDefaultAction(
                    FormState.Current.DataModifications.Append(pb),
                    () => get("Separate value-changed action", TextControlSetup.Create(valueChangedAction: new PostBackFormAction(pb)))(id)));
     },
     get("Read-only", TextControlSetup.CreateReadOnly()), get("Multiline", TextControlSetup.Create(numberOfRows: 3)),
     get("Multiline, max length 25", TextControlSetup.Create(numberOfRows: 3), maxLength: 25),
     get("Multiline with placeholder", TextControlSetup.Create(numberOfRows: 3, placeholder: "Type longer text here")),
     get("Multiline auto-fill", TextControlSetup.Create(numberOfRows: 3, autoFillTokens: "street-address")),
     get("Multiline auto-complete", TextControlSetup.CreateAutoComplete(TestService.GetInfo(), numberOfRows: 3)),
     get("Multiline, spell-checking disabled", TextControlSetup.Create(numberOfRows: 3, checksSpellingAndGrammar: false)),
     get("Multiline, spell-checking enabled", TextControlSetup.Create(numberOfRows: 3, checksSpellingAndGrammar: true)), id => {
         var pb = PostBack.CreateIntermediate(null, id: id);
         return(FormState.ExecuteWithDataModificationsAndDefaultAction(
                    FormState.Current.DataModifications.Append(pb),
                    () => get(
                        "Multiline with separate value-changed action",
                        TextControlSetup.Create(numberOfRows: 3, valueChangedAction: new PostBackFormAction(pb)))(id)));
     },
     get("Multiline read-only", TextControlSetup.CreateReadOnly(numberOfRows: 3)), get("Obscured", TextControlSetup.CreateObscured()),
     get("Obscured, max length 25", TextControlSetup.CreateObscured(), maxLength: 25),
     get("Obscured with placeholder", TextControlSetup.CreateObscured(placeholder: "Type here")),
     get("Obscured auto-fill", TextControlSetup.CreateObscured(autoFillTokens: "new-password")), id => {
         var pb = PostBack.CreateIntermediate(null, id: id);
         return(FormState.ExecuteWithDataModificationsAndDefaultAction(
                    FormState.Current.DataModifications.Append(pb),
                    () => get(
                        "Obscured with separate value-changed action",
                        TextControlSetup.CreateObscured(valueChangedAction: new PostBackFormAction(pb)))(id)));
     }
 };
Пример #21
0
        private FlowComponent getTagSection(DataValue <string> filter, UpdateRegionSet resultUpdateRegions)
        {
            var tags = ArticleTagsTableRetrieval.GetRows()
                       .Select(i => i.TagId)
                       .GroupBy(i => i)
                       .OrderByDescending(i => i.Count())
                       .Take(20)
                       .Select(i => TagsTableRetrieval.GetRowMatchingId(i.Key));

            return(new Section(
                       "Popular Tags",
                       new WrappingList(
                           tags.Select(
                               i => (WrappingListItem) new EwfButton(
                                   new StandardButtonStyle(i.TagName, buttonSize: ButtonSize.ShrinkWrap),
                                   behavior: new PostBackBehavior(
                                       postBack: PostBack.CreateIntermediate(
                                           resultUpdateRegions.ToCollection(),
                                           id: PostBack.GetCompositeId("tag", i.TagId.ToString()),
                                           modificationMethod: () => filter.Value = "tag{0}".FormatWith(i.TagId)))).ToComponentListItem()),
                           generalSetup: new ComponentListSetup(classes: ElementClasses.Tag)).ToCollection(),
                       style: SectionStyle.Box));
        }
        private ControlListItem getNonIdItem(int i)
        {
            var rs = new UpdateRegionSet();
            var pb = PostBack.CreateIntermediate(rs.ToSingleElementArray(), DataUpdate, id: PostBack.GetCompositeId("nonId", i.ToString()));

            var itemStack = ControlStack.Create(true);

            if (info.NonIdItemStates.ElementAt(i) == 1)
            {
                itemStack.AddControls(new EwfTextBox("Item {0}".FormatWith(i)));
            }
            else
            {
                itemStack.AddText("Item {0}".FormatWith(i));
            }
            itemStack.AddControls(
                new PostBackButton(pb, new ButtonActionControlStyle("Toggle", buttonSize: ButtonActionControlStyle.ButtonSize.ShrinkWrap), usesSubmitBehavior: false));

            pb.AddModificationMethod(
                () => parametersModification.NonIdItemStates = parametersModification.NonIdItemStates.Select((state, index) => index == i ? (state + 1) % 2 : state));

            return(new ControlListItem(itemStack.ToSingleElementArray(), updateRegionSet: rs));
        }
Пример #23
0
        private IReadOnlyCollection <FlowComponent> getNonIdListRegionComponents()
        {
            var components = new List <FlowComponent>();

            var addRs    = new UpdateRegionSet();
            var removeRs = new UpdateRegionSet();

            components.Add(
                new LineList(
                    new EwfButton(
                        new StandardButtonStyle("Add Two Items"),
                        behavior: new PostBackBehavior(
                            postBack: PostBack.CreateIntermediate(
                                addRs.ToCollection(),
                                id: "nonIdAdd",
                                firstModificationMethod: () => parametersModification.NonIdItemStates = parametersModification.NonIdItemStates.Concat(new[] { 0, 0 }))))
                    .ToCollection()
                    .Append(
                        new EwfButton(
                            new StandardButtonStyle("Remove Two Items"),
                            behavior: new PostBackBehavior(
                                postBack: PostBack.CreateIntermediate(
                                    removeRs.ToCollection(),
                                    id: "nonIdRemove",
                                    firstModificationMethod: () =>
                                    parametersModification.NonIdItemStates =
                                        parametersModification.NonIdItemStates.Take(parametersModification.NonIdItemStates.Count() - 2)))))
                    .Select(i => (LineListItem)i.ToCollection().ToComponentListItem())));

            var stack = new StackList(
                Enumerable.Range(0, info.NonIdItemStates.Count()).Select(getNonIdItem),
                setup: new ComponentListSetup(
                    tailUpdateRegions: new[] { new TailUpdateRegion(addRs.ToCollection(), 0), new TailUpdateRegion(removeRs.ToCollection(), 2) }));

            components.Add(new Section("Control List With Non-ID Items", stack.ToCollection(), style: SectionStyle.Box));
            return(components);
        }
Пример #24
0
        private static PhrasingComponent getFavoriteActionComponent(
            ArticlesRetrieval.Row article, ILookup <int, FavoritesTableRetrieval.Row> favoritesByArticleId)
        {
            var count = favoritesByArticleId[article.ArticleId].Count().ToString();

            if (AppTools.User == null)
            {
                return(new EwfHyperlink(User.GetInfo(), new StandardHyperlinkStyle(count, icon: new ActionComponentIcon(new FontAwesomeIcon("fa-heart-o")))));
            }

            var       rs = new UpdateRegionSet();
            EwfButton button;

            if (FavoritesTableRetrieval.GetRowMatchingPk(AppTools.User.UserId, article.ArticleId, returnNullIfNoMatch: true) == null)
            {
                button = new EwfButton(
                    new StandardButtonStyle(count, icon: new ActionComponentIcon(new FontAwesomeIcon("fa-heart-o"))),
                    behavior: new PostBackBehavior(
                        postBack: PostBack.CreateIntermediate(
                            rs.ToCollection(),
                            id: PostBack.GetCompositeId("favorite", article.ArticleId.ToString()),
                            modificationMethod: () => FavoritesModification.InsertRow(AppTools.User.UserId, article.ArticleId))));
            }
            else
            {
                button = new EwfButton(
                    new StandardButtonStyle(count, icon: new ActionComponentIcon(new FontAwesomeIcon("fa-heart"))),
                    behavior: new PostBackBehavior(
                        postBack: PostBack.CreateIntermediate(
                            rs.ToCollection(),
                            id: PostBack.GetCompositeId("unfavorite", article.ArticleId.ToString()),
                            modificationMethod: () => FavoritesModification.DeleteRows(
                                new FavoritesTableEqualityConditions.UserId(AppTools.User.UserId),
                                new FavoritesTableEqualityConditions.ArticleId(article.ArticleId)))));
            }
            return(new PhrasingIdContainer(button.ToCollection(), updateRegionSets: rs.ToCollection()));
        }
Пример #25
0
        private IEnumerable <FlowComponent> getBasicRegionComponents()
        {
            var rs = new UpdateRegionSet();
            var pb = PostBack.CreateIntermediate(rs.ToCollection(), id: "basic");

            yield return(new Paragraph(
                             new EwfButton(new StandardButtonStyle("Toggle Basic Region Below"), behavior: new PostBackBehavior(postBack: pb)).ToCollection()));

            var regionComponents  = new List <FlowComponent>();
            var dynamicFieldValue = new DataValue <string>();

            FormState.ExecuteWithDataModificationsAndDefaultAction(
                pb.ToCollection(),
                () => {
                if (info.Toggled)
                {
                    regionComponents.AddRange(
                        dynamicFieldValue.ToTextControl(true, value: "This was just added!")
                        .ToFormItem(label: "Dynamic Field".ToComponents())
                        .ToComponentCollection());
                }
                else
                {
                    regionComponents.Add(new Paragraph("Nothing here yet.".ToComponents()));
                }
            });
            yield return(new FlowIdContainer(
                             new Section("Basic Update Region", regionComponents, style: SectionStyle.Box).ToCollection(),
                             updateRegionSets: rs.ToCollection()));

            pb.AddModificationMethod(() => parametersModification.Toggled = !parametersModification.Toggled);
            pb.AddModificationMethod(
                () => AddStatusMessage(
                    StatusMessageType.Info,
                    info.Toggled ? "Dynamic field value was '{0}'.".FormatWith(dynamicFieldValue.Value) : "Dynamic field added."));
        }
 private IReadOnlyCollection <Func <string, FormItem> > getControls() =>
 new[]
 {
     get("Standard", null), get("[1,2] with .25 step", null, minValue: 1, maxValue: 2, valueStep: .25m),
     get("Placeholder", NumberControlSetup.Create(placeholder: "Type here")),
     get("Birthday year auto-fill", NumberControlSetup.Create(autoFillTokens: "bday-year")),
     get("Auto-complete", NumberControlSetup.CreateAutoComplete(TestService.GetInfo())), id => {
         var pb = PostBack.CreateIntermediate(null, id: id);
         return(FormState.ExecuteWithDataModificationsAndDefaultAction(
                    FormState.Current.DataModifications.Append(pb),
                    () => get("Separate value-changed action", NumberControlSetup.Create(valueChangedAction: new PostBackFormAction(pb)))(id)));
     },
     new Func <Func <string, FormItem> >(
         () => {
         var pmv = new PageModificationValue <decimal?>();
         return(get("Page modification", NumberControlSetup.Create(pageModificationValue: pmv), pageModificationValue: pmv));
     })(),
     get("Read-only", NumberControlSetup.CreateReadOnly()), getImprecise("Imprecise", null),
     getImprecise("Imprecise [1,2] with .25 step", null, minValue: 1, maxValue: 2, valueStep: .25m), id => {
         var pb = PostBack.CreateIntermediate(null, id: id);
         return(FormState.ExecuteWithDataModificationsAndDefaultAction(
                    FormState.Current.DataModifications.Append(pb),
                    () => getImprecise(
                        "Imprecise with separate value-changed action",
                        ImpreciseNumberControlSetup.Create(valueChangedAction: new PostBackFormAction(pb)))(id)));
     },
     new Func <Func <string, FormItem> >(
         () => {
         var pmv = new PageModificationValue <decimal>();
         return(getImprecise(
                    "Imprecise with page modification",
                    ImpreciseNumberControlSetup.Create(pageModificationValue: pmv),
                    pageModificationValue: pmv));
     })(),
     getImprecise("Imprecise read-only", ImpreciseNumberControlSetup.CreateReadOnly())
 };
Пример #27
0
        private FormItem getTagFormItem(DataValue <IReadOnlyCollection <int> > tagIds)
        {
            var addUpdateRegions    = new UpdateRegionSet();
            var tagName             = new DataValue <string>();
            var removeUpdateRegions = new UpdateRegionSet();

            return(new FlowIdContainer(
                       FormState.ExecuteWithDataModificationsAndDefaultAction(
                           PostBack.CreateIntermediate(addUpdateRegions.ToCollection(), id: "addTag", modificationMethod: () => addTag(tagIds, tagName)).ToCollection(),
                           () => new TextControl(
                               "",
                               false,
                               maxLength: TagsTable.TagNameColumn.Size,
                               validationMethod: (postBackValue, validator) => tagName.Value = postBackValue))
                       .ToFormItem()
                       .ToComponentCollection(),
                       updateRegionSets: addUpdateRegions.ToCollection()).Append <FlowComponent>(new LineBreak())
                   .Append(
                       new PhrasingIdContainer(
                           getTagListComponents(tagIds, removeUpdateRegions),
                           updateRegionSets: addUpdateRegions.ToCollection().Append(removeUpdateRegions)))
                   .Materialize()
                   .ToFormItem(label: "Enter tags".ToComponents()));
        }
        protected override void loadData()
        {
            var itemGroups = Enumerable.Range(1, 2)
                             .Select(
                group => ColumnPrimaryItemGroup.Create(
                    "Group {0}".FormatWith(group).ToComponents(),
                    groupActions:
                    new ButtonSetup(
                        "Action 1",
                        behavior: new PostBackBehavior(
                            postBack: PostBack.CreateIntermediate(
                                null,
                                id: PostBack.GetCompositeId(group.ToString(), "action1"),
                                firstModificationMethod: () => AddStatusMessage(StatusMessageType.Info, "Action 1")))).Append(
                        new ButtonSetup(
                            "Action 2",
                            behavior: new PostBackBehavior(
                                postBack: PostBack.CreateIntermediate(
                                    null,
                                    id: PostBack.GetCompositeId(group.ToString(), "action2"),
                                    firstModificationMethod: () => AddStatusMessage(StatusMessageType.Info, "Action 2")))))
                    .Materialize(),
                    selectedItemActions: group == 1
                                                                             ? SelectedItemAction.CreateWithIntermediatePostBackBehavior <int>(
                        "Echo group IDs",
                        null,
                        ids => AddStatusMessage(
                            StatusMessageType.Info,
                            StringTools.GetEnglishListPhrase(ids.Select(i => i.ToString()), true)))
                    .ToCollection()
                                                                             : Enumerable.Empty <SelectedItemAction <int> >().Materialize(),
                    items: Enumerable.Range(1, 5)
                    .Select(
                        i => EwfTableItem.Create(
                            EwfTableItemSetup.Create(
                                activationBehavior: ElementActivationBehavior.CreateRedirectScript(ActionControls.GetInfo()),
                                id: new SpecifiedValue <int>(group * 10 + i)),
                            i.ToString().ToCell(),
                            ((i * 2) + Environment.NewLine + "extra stuff").ToCell()))))
                             .Materialize();

            place.AddControlsReturnThis(
                ColumnPrimaryTable.Create(
                    caption: "My table",
                    subCaption: "A new table implementation",
                    allowExportToExcel: true,
                    tableActions: new ButtonSetup(
                        "Action",
                        behavior: new PostBackBehavior(
                            postBack: PostBack.CreateIntermediate(
                                null,
                                id: "action",
                                firstModificationMethod: () => AddStatusMessage(StatusMessageType.Info, "You clicked action.")))).ToCollection(),
                    selectedItemActions: SelectedItemAction
                    .CreateWithIntermediatePostBackBehavior <int>(
                        "Echo IDs",
                        null,
                        ids => AddStatusMessage(StatusMessageType.Info, StringTools.GetEnglishListPhrase(ids.Select(i => i.ToString()), true)))
                    .Append(
                        SelectedItemAction.CreateWithIntermediatePostBackBehavior <int>(
                            "With confirmation",
                            null,
                            ids => AddStatusMessage(StatusMessageType.Info, StringTools.GetEnglishListPhrase(ids.Select(i => i.ToString()), true)),
                            confirmationDialogContent: "Are you sure?".ToComponents()))
                    .Materialize(),
                    fields: new[] { new EwfTableField(size: 1.ToPercentage()), new EwfTableField(size: 2.ToPercentage()) })
                .AddItemGroups(itemGroups)
                .ToCollection()
                .GetControls());
        }
        void ControlTreeDataLoader.LoadData()
        {
            basicBody.Attributes.Add("onpagehide", "deactivateProcessingDialog();");
            form.Action = EwfPage.Instance.InfoAsBaseType.GetUrl();

            ph.AddControlsReturnThis(
                new NamingPlaceholder(
                    EwfPage.Instance.StatusMessages.Any() && statusMessagesDisplayAsNotification()
                                                ? new Block {
                CssClass = notificationSpacerClass
            }.ToCollection()
                                                : Enumerable.Empty <Control>()));

            var warningLines = new List <IReadOnlyCollection <PhrasingComponent> >();

            if (!ConfigurationStatics.IsLiveInstallation)
            {
                var components = new List <PhrasingComponent>();
                components.Add(new FontAwesomeIcon("fa-exclamation-triangle", "fa-lg"));
                components.AddRange(" This is not the live system. Changes made here will be lost and are not recoverable. ".ToComponents());
                if (ConfigurationStatics.IsIntermediateInstallation && AppRequestState.Instance.IntermediateUserExists)
                {
                    components.AddRange(
                        new EwfButton(
                            new StandardButtonStyle("Log out", buttonSize: ButtonSize.ShrinkWrap),
                            behavior: new PostBackBehavior(
                                postBack: PostBack.CreateFull(
                                    id: "ewfIntermediateLogOut",
                                    firstModificationMethod: NonLiveInstallationStatics.ClearIntermediateAuthenticationCookie,
                                    actionGetter: () => new PostBackAction(new ExternalResourceInfo(NetTools.HomeUrl))))).Concat(" ".ToComponents()));
                }
                components.Add(
                    new EwfButton(
                        new StandardButtonStyle(
                            "Hide this warning",
                            buttonSize: ButtonSize.ShrinkWrap,
                            icon: new ActionComponentIcon(new FontAwesomeIcon("fa-eye-slash"))),
                        behavior: new PostBackBehavior(
                            postBack: PostBack.CreateIntermediate(
                                null,
                                id: "ewfHideNonLiveWarnings",
                                firstModificationMethod: NonLiveInstallationStatics.SetWarningsHiddenCookie))));
                if (ConfigurationStatics.IsIntermediateInstallation && AppRequestState.Instance.IntermediateUserExists)
                {
                    var boxId = new ModalBoxId();
                    components.AddRange(
                        " ".ToComponents()
                        .Append(
                            new EwfButton(
                                new StandardButtonStyle("Get link", buttonSize: ButtonSize.ShrinkWrap, icon: new ActionComponentIcon(new FontAwesomeIcon("fa-link"))),
                                behavior: new OpenModalBehavior(
                                    boxId,
                                    etherealChildren: new ModalBox(
                                        boxId,
                                        true,
                                        FormItemList.CreateGrid(
                                            1,
                                            items: new[] { false, true }.Select(
                                                i => {
                        var url = AppRequestState.Instance.Url;
                        if (AppRequestState.Instance.UserAccessible && AppRequestState.Instance.ImpersonatorExists)
                        {
                            url = SelectUser.GetInfo(
                                url,
                                optionalParameterPackage: new SelectUser.OptionalParameterPackage {
                                User = AppTools.User.Email
                            })
                                  .GetUrl();
                        }
                        url = IntermediateLogIn.GetInfo(
                            url,
                            new IntermediateLogIn.OptionalParameterPackage
                        {
                            Password = ConfigurationStatics.SystemGeneralProvider.IntermediateLogInPassword, HideWarnings = i
                        })
                              .GetUrl();
                        return(new GenericPhrasingContainer(
                                   url.ToComponents(),
                                   classes: new ElementClass("ewfIntermediateUrl" /* This is used by EWF CSS files. */)).ToFormItem(
                                   label: i ? "Non-live warnings hidden:".ToComponents() : "Standard:".ToComponents()));
                    })
                                            .Materialize())
                                        .ToCollection()).ToCollection()))));
                }
                warningLines.Add(components);
            }

            if (AppRequestState.Instance.UserAccessible && AppRequestState.Instance.ImpersonatorExists &&
                (!ConfigurationStatics.IsIntermediateInstallation || AppRequestState.Instance.IntermediateUserExists))
            {
                warningLines.Add(
                    "User impersonation is in effect. ".ToComponents()
                    .Append(
                        new EwfHyperlink(
                            SelectUser.GetInfo(AppRequestState.Instance.Url),
                            new ButtonHyperlinkStyle("Change user", buttonSize: ButtonSize.ShrinkWrap)))
                    .Concat(" ".ToComponents())
                    .Append(
                        new EwfButton(
                            new StandardButtonStyle("End impersonation", buttonSize: ButtonSize.ShrinkWrap),
                            behavior: new PostBackBehavior(
                                postBack: PostBack.CreateFull(
                                    id: "ewfEndImpersonation",
                                    firstModificationMethod: UserImpersonationStatics.EndImpersonation,
                                    actionGetter: () => new PostBackAction(new ExternalResourceInfo(NetTools.HomeUrl))))))
                    .Materialize());
            }

            if (warningLines.Any())
            {
                ph.AddControlsReturnThis(
                    new GenericFlowContainer(
                        warningLines.Aggregate((components, line) => components.Append(new LineBreak()).Concat(line).Materialize()),
                        displaySetup: new DisplaySetup(ConfigurationStatics.IsLiveInstallation || !NonLiveInstallationStatics.WarningsHiddenCookieExists()),
                        classes: topWarningContainerClass).ToCollection()
                    .GetControls());
            }

            // This is used by the EWF JavaScript file.
            const string clickBlockerId = "ewfClickBlocker";

            ph2.AddControlsReturnThis(
                new Block {
                ClientIDMode = ClientIDMode.Static, ID = clickBlockerId, CssClass = clickBlockerInactiveClass
            },
                new PlaceHolder().AddControlsReturnThis(getProcessingDialog().GetControls()),
                new NamingPlaceholder(getStatusMessageControl()));
        }
Пример #30
0
        void ControlTreeDataLoader.LoadData()
        {
            using (MiniProfiler.Current.Step("EWF - Load table data")) {
                FormState.ExecuteWithDataModificationsAndDefaultAction(
                    dataModifications,
                    () => {
                    if (hideIfEmpty && itemGroups.All(itemGroup => !itemGroup.Items.Any()))
                    {
                        Visible = false;
                        return;
                    }

                    SetUpTableAndCaption(this, style, classes, caption, subCaption);

                    var visibleItemGroupsAndItems = new List <Tuple <EwfTableItemGroup, IReadOnlyCollection <EwfTableItem> > >();
                    foreach (var itemGroup in itemGroups)
                    {
                        var visibleItems = itemGroup.Items.Take(CurrentItemLimit - visibleItemGroupsAndItems.Sum(i => i.Item2.Count)).Select(i => i());
                        visibleItemGroupsAndItems.Add(Tuple.Create <EwfTableItemGroup, IReadOnlyCollection <EwfTableItem> >(itemGroup, visibleItems.ToImmutableArray()));
                        if (visibleItemGroupsAndItems.Sum(i => i.Item2.Count) == CurrentItemLimit)
                        {
                            break;
                        }
                    }

                    var fields = GetFields(specifiedFields, headItems.AsReadOnly(), visibleItemGroupsAndItems.SelectMany(i => i.Item2));
                    if (!fields.Any())
                    {
                        fields = new EwfTableField().ToCollection();
                    }

                    addColumnSpecifications(fields);

                    var allVisibleItems = new List <EwfTableItem>();

                    var itemLimitingUpdateRegionSet = new UpdateRegionSet();
                    var headRows =
                        buildRows(
                            getItemLimitingAndGeneralActionsItem(fields.Count, itemLimitingUpdateRegionSet).Concat(getItemActionsItem(fields.Count)).ToList(),
                            Enumerable.Repeat(new EwfTableField(), fields.Count).ToArray(),
                            null,
                            false,
                            null,
                            null,
                            allVisibleItems).Concat(buildRows(headItems, fields, null, true, null, null, allVisibleItems)).ToArray();
                    if (headRows.Any())
                    {
                        Controls.Add(new WebControl(HtmlTextWriterTag.Thead).AddControlsReturnThis(headRows));
                    }

                    var bodyRowGroupsAndRows = new List <Tuple <WebControl, ImmutableArray <Control> > >();
                    var updateRegionSetListsAndStaticRowGroupCounts = new List <Tuple <IReadOnlyCollection <UpdateRegionSet>, int> >();
                    for (var visibleGroupIndex = 0; visibleGroupIndex < visibleItemGroupsAndItems.Count; visibleGroupIndex += 1)
                    {
                        var groupAndItems          = visibleItemGroupsAndItems[visibleGroupIndex];
                        var useContrastForFirstRow = visibleItemGroupsAndItems.Where((group, i) => i < visibleGroupIndex).Sum(i => i.Item2.Count) % 2 == 1;
                        var groupBodyRows          = buildRows(groupAndItems.Item2, fields, useContrastForFirstRow, false, null, null, allVisibleItems).ToImmutableArray();
                        var rowGroup =
                            new WebControl(HtmlTextWriterTag.Tbody).AddControlsReturnThis(
                                buildRows(
                                    groupAndItems.Item1.GetHeadItems(fields.Count),
                                    Enumerable.Repeat(new EwfTableField(), fields.Count).ToArray(),
                                    null,
                                    true,
                                    null,
                                    null,
                                    allVisibleItems).Concat(new NamingPlaceholder(groupBodyRows).ToCollection()));
                        bodyRowGroupsAndRows.Add(Tuple.Create(rowGroup, groupBodyRows));

                        var cachedVisibleGroupIndex = visibleGroupIndex;
                        EwfPage.Instance.AddUpdateRegionLinker(
                            new LegacyUpdateRegionLinker(
                                rowGroup,
                                "tail",
                                from region in groupAndItems.Item1.RemainingData.Value.TailUpdateRegions
                                let staticRowCount = itemGroups[cachedVisibleGroupIndex].Items.Count - region.UpdatingItemCount
                                                     select new LegacyPreModificationUpdateRegion(region.Sets, () => groupBodyRows.Skip(staticRowCount), staticRowCount.ToString),
                                arg => groupBodyRows.Skip(int.Parse(arg))));

                        // If item limiting is enabled, include all subsequent item groups in tail update regions since any number of items could be appended.
                        if (defaultItemLimit != DataRowLimit.Unlimited)
                        {
                            updateRegionSetListsAndStaticRowGroupCounts.Add(
                                Tuple.Create <IReadOnlyCollection <UpdateRegionSet>, int>(
                                    groupAndItems.Item1.RemainingData.Value.TailUpdateRegions.SelectMany(i => i.Sets).ToImmutableArray(),
                                    visibleGroupIndex + 1));
                        }
                    }
                    Controls.Add(new NamingPlaceholder(bodyRowGroupsAndRows.Select(i => i.Item1)));

                    if (defaultItemLimit != DataRowLimit.Unlimited)
                    {
                        var oldItemLimit   = CurrentItemLimit;
                        var lowerItemLimit = new Lazy <int>(() => Math.Min(oldItemLimit, CurrentItemLimit));

                        var itemLimitingTailUpdateRegionControlGetter = new Func <int, IEnumerable <Control> >(
                            staticItemCount => {
                            var rowCount = 0;
                            for (var groupIndex = 0; groupIndex < bodyRowGroupsAndRows.Count; groupIndex += 1)
                            {
                                var rows  = bodyRowGroupsAndRows[groupIndex].Item2;
                                rowCount += rows.Length;
                                if (rowCount < staticItemCount)
                                {
                                    continue;
                                }
                                return(rows.Skip(rows.Length - (rowCount - staticItemCount)).Concat(bodyRowGroupsAndRows.Skip(groupIndex + 1).Select(i => i.Item1)));
                            }
                            return(ImmutableArray <Control> .Empty);
                        });

                        EwfPage.Instance.AddUpdateRegionLinker(
                            new LegacyUpdateRegionLinker(
                                this,
                                "itemLimitingTail",
                                new LegacyPreModificationUpdateRegion(
                                    itemLimitingUpdateRegionSet.ToCollection(),
                                    () => itemLimitingTailUpdateRegionControlGetter(lowerItemLimit.Value),
                                    () => lowerItemLimit.Value.ToString()).ToCollection(),
                                arg => itemLimitingTailUpdateRegionControlGetter(int.Parse(arg))));
                    }

                    EwfPage.Instance.AddUpdateRegionLinker(
                        new LegacyUpdateRegionLinker(
                            this,
                            "tail",
                            from region in
                            tailUpdateRegions.Select(i => new { sets = i.Sets, staticRowGroupCount = itemGroups.Count - i.UpdatingItemCount })
                            .Concat(updateRegionSetListsAndStaticRowGroupCounts.Select(i => new { sets = i.Item1, staticRowGroupCount = i.Item2 }))
                            select
                            new LegacyPreModificationUpdateRegion(
                                region.sets,
                                () => bodyRowGroupsAndRows.Skip(region.staticRowGroupCount).Select(i => i.Item1),
                                region.staticRowGroupCount.ToString),
                            arg => bodyRowGroupsAndRows.Skip(int.Parse(arg)).Select(i => i.Item1)));

                    var itemCount            = itemGroups.Sum(i => i.Items.Count);
                    var itemLimitingRowGroup = new List <Control>();
                    if (CurrentItemLimit < itemCount)
                    {
                        var nextLimit          = EnumTools.GetValues <DataRowLimit>().First(i => i > (DataRowLimit)CurrentItemLimit);
                        var itemIncrementCount = Math.Min((int)nextLimit, itemCount) - CurrentItemLimit;
                        var button             = new PostBackButton(
                            new TextActionControlStyle("Show " + itemIncrementCount + " more item" + (itemIncrementCount != 1 ? "s" : "")),
                            usesSubmitBehavior: false,
                            postBack:
                            PostBack.CreateIntermediate(
                                itemLimitingUpdateRegionSet.ToCollection(),
                                id: PostBack.GetCompositeId(postBackIdBase, "showMore"),
                                firstModificationMethod: () => EwfPage.Instance.PageState.SetValue(this, itemLimitPageStateKey, (int)nextLimit)));
                        var item        = new EwfTableItem(button.ToCell(new TableCellSetup(fieldSpan: fields.Count)));
                        var useContrast = visibleItemGroupsAndItems.Sum(i => i.Item2.Count) % 2 == 1;
                        itemLimitingRowGroup.Add(
                            new WebControl(HtmlTextWriterTag.Tbody).AddControlsReturnThis(
                                buildRows(
                                    item.ToCollection().ToList(),
                                    Enumerable.Repeat(new EwfTableField(), fields.Count).ToArray(),
                                    useContrast,
                                    false,
                                    null,
                                    null,
                                    allVisibleItems)));
                    }
                    Controls.Add(
                        new NamingPlaceholder(
                            itemLimitingRowGroup,
                            updateRegionSets:
                            itemLimitingUpdateRegionSet.ToCollection()
                            .Concat(
                                itemGroups.SelectMany(i => i.RemainingData.Value.TailUpdateRegions).ToImmutableArray().Concat(tailUpdateRegions).SelectMany(i => i.Sets))));

                    // Assert that every visible item in the table has the same number of cells and store a data structure for below.
                    var cellPlaceholderListsForItems = TableOps.BuildCellPlaceholderListsForItems(allVisibleItems, fields.Count);

                    if (!disableEmptyFieldDetection)
                    {
                        AssertAtLeastOneCellPerField(fields, cellPlaceholderListsForItems);
                    }
                });
            }
        }