From 79ac5233156d20e640223b4ab7050cffbb975d79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Herceg?= Date: Fri, 12 Jul 2024 22:48:09 +0200 Subject: [PATCH 1/3] Added PageNumberTemplate and capabilities in DataPager control --- src/Framework/Framework/Controls/DataPager.cs | 106 +++++++++++++++--- .../DataPager/DataPagerTemplatesViewModel.cs | 55 +++++++++ .../DataPager/DataPagerViewModel.cs | 2 + .../DataPager/DataPagerTemplates.dothtml | 52 +++++++++ .../Abstractions/SamplesRouteUrls.designer.cs | 1 + .../Tests/Tests/Control/DataPagerTests.cs | 22 ++++ 6 files changed, 222 insertions(+), 16 deletions(-) create mode 100644 src/Samples/Common/ViewModels/ControlSamples/DataPager/DataPagerTemplatesViewModel.cs create mode 100644 src/Samples/Common/Views/ControlSamples/DataPager/DataPagerTemplates.dothtml diff --git a/src/Framework/Framework/Controls/DataPager.cs b/src/Framework/Framework/Controls/DataPager.cs index 32e2d7781b..d0674fad66 100644 --- a/src/Framework/Framework/Controls/DataPager.cs +++ b/src/Framework/Framework/Controls/DataPager.cs @@ -93,6 +93,20 @@ public ITemplate? NextPageTemplate public static readonly DotvvmProperty NextPageTemplateProperty = DotvvmProperty.Register(c => c.NextPageTemplate, null); + /// + /// Gets or sets the template of the button which moves the user to the numbered page. + /// + [MarkupOptions(AllowBinding = false, MappingMode = MappingMode.InnerElement)] + [ConstantDataContextChange(typeof(int[]), order: 0)] + [CollectionElementDataContextChange(order: 1)] + public ITemplate? PageNumberTemplate + { + get { return (ITemplate?)GetValue(PageNumberTemplateProperty); } + set { SetValue(PageNumberTemplateProperty, value); } + } + public static readonly DotvvmProperty PageNumberTemplateProperty = + DotvvmProperty.Register(c => c.PageNumberTemplate, null); + /// /// Gets or sets whether a hyperlink should be rendered for the current page number. If set to false, only a plain text is rendered. /// @@ -126,6 +140,27 @@ public bool Enabled public static readonly DotvvmProperty EnabledProperty = DotvvmPropertyWithFallback.Register(nameof(Enabled), FormControls.EnabledProperty); + /// + /// Gets or sets styles for the list item element (<li>) rendered by the component. + /// + public HtmlCapability ListItemHtmlCapability + { + get => (HtmlCapability)ListItemHtmlCapabilityProperty.GetValue(this); + set => ListItemHtmlCapabilityProperty.SetValue(this, value); + } + public static readonly DotvvmCapabilityProperty ListItemHtmlCapabilityProperty = DotvvmCapabilityProperty.RegisterCapability("ListItem"); + + /// + /// Gets or sets styles for the link buttons rendered by the component. + /// + public HtmlCapability LinkHtmlCapability + { + get => (HtmlCapability)LinkHtmlCapabilityProperty.GetValue(this); + set => LinkHtmlCapabilityProperty.SetValue(this, value); + } + public static readonly DotvvmCapabilityProperty LinkHtmlCapabilityProperty = DotvvmCapabilityProperty.RegisterCapability("Link"); + + /// /// Gets or sets the (static) command that will be triggered when the DataPager needs to load data (when navigating to different page). /// The command accepts one argument of type and should return a new or . @@ -138,14 +173,36 @@ public ICommandBinding? LoadData public static readonly DotvvmProperty LoadDataProperty = DotvvmProperty.Register(nameof(LoadData)); + /// + /// Gets or sets the CSS class to be applied to the currently active page number. + /// + [MarkupOptions(AllowBinding = false)] + public string ActiveItemCssClass + { + get { return (string)GetValue(ActiveItemCssClassProperty); } + set { SetValue(ActiveItemCssClassProperty, value); } + } + public static readonly DotvvmProperty ActiveItemCssClassProperty + = DotvvmProperty.Register(c => c.ActiveItemCssClass, "active"); + + /// + /// Gets or sets the CSS class that to be applied to the disabled items. + /// + [MarkupOptions(AllowBinding = false)] + public string DisabledItemCssClass + { + get { return (string)GetValue(DisabledItemCssClassProperty); } + set { SetValue(DisabledItemCssClassProperty, value); } + } + public static readonly DotvvmProperty DisabledItemCssClassProperty + = DotvvmProperty.Register(c => c.DisabledItemCssClass, "disabled"); + protected HtmlGenericControl? ContentWrapper { get; set; } protected HtmlGenericControl? GoToFirstPageButton { get; set; } protected HtmlGenericControl? GoToPreviousPageButton { get; set; } protected Repeater? NumberButtonsRepeater { get; set; } protected HtmlGenericControl? GoToNextPageButton { get; set; } protected HtmlGenericControl? GoToLastPageButton { get; set; } - protected virtual string ActiveItemCssClass => "active"; - protected virtual string DisabledItemCssClass => "disabled"; protected internal override void OnLoad(IDotvvmRequestContext context) { @@ -196,7 +253,7 @@ protected virtual void DataBind(Hosting.IDotvvmRequestContext context) if (pagerBindings.PageNumbers is {}) { // number fields - var liTemplate = CreatePageNumberButton(globalEnabled, pagerBindings, context); + var liTemplate = CreatePageNumberButton(globalEnabled, PageNumberTemplate, pagerBindings, context); AddItemCssClass(liTemplate, context); NumberButtonsRepeater = new Repeater() { @@ -250,22 +307,23 @@ protected virtual HtmlGenericControl CreateWrapperList() protected override void AddVisibleAttributeOrBinding(in RenderState r, IHtmlWriter writer) { } // handled by the wrapper list - protected virtual HtmlGenericControl CreatePageNumberButton(ValueOrBinding globalEnabled, DataPagerBindings pagerBindings, IDotvvmRequestContext context) + protected virtual HtmlGenericControl CreatePageNumberButton(ValueOrBinding globalEnabled, ITemplate? userDefinedContentTemplate, DataPagerBindings pagerBindings, IDotvvmRequestContext context) { - var liTemplate = new HtmlGenericControl("li"); + var liTemplate = new HtmlGenericControl("li", ListItemHtmlCapability); liTemplate.CssClasses.Add(ActiveItemCssClass, new ValueOrBinding(pagerBindings.NotNull().IsActivePage.NotNull())); - var link = new LinkButton(); + + var link = new LinkButton().SetCapability(LinkHtmlCapability); + link.SetBinding(ButtonBase.ClickProperty, pagerBindings.NotNull().GoToPage.NotNull()); - SetPageNumberButtonContent(link, pagerBindings, context); + SetPageNumberButtonContent(context, link, pagerBindings, userDefinedContentTemplate); if (!RenderLinkForCurrentPage) link.SetBinding(IncludeInPageProperty, pagerBindings.IsActivePage.NotNull().Negate()); if (!true.Equals(globalEnabled)) link.SetValue(ButtonBase.EnabledProperty, globalEnabled); liTemplate.Children.Add(link); if (!RenderLinkForCurrentPage) { - var notLink = new Literal(); - SetPageNumberSpanContent(notLink, pagerBindings, context); - notLink.RenderSpanElement = true; + var notLink = new HtmlGenericControl("span").SetCapability(LinkHtmlCapability); + SetPageNumberSpanContent(context, notLink, pagerBindings, userDefinedContentTemplate); notLink.SetBinding(IncludeInPageProperty, pagerBindings.IsActivePage); liTemplate.Children.Add(notLink); } @@ -274,8 +332,10 @@ protected virtual HtmlGenericControl CreatePageNumberButton(ValueOrBinding protected virtual HtmlGenericControl CreateNavigationButton(string defaultText, ITemplate? userDefinedContentTemplate, object enabledValue, ICommandBinding clickCommandBindingExpression,IDotvvmRequestContext context) { - var li = new HtmlGenericControl("li"); - var link = new LinkButton(); + var li = new HtmlGenericControl("li", ListItemHtmlCapability); + + var link = new LinkButton().SetCapability(LinkHtmlCapability); + SetNavigationButtonContent(context, link, defaultText, userDefinedContentTemplate); link.SetBinding(ButtonBase.ClickProperty, clickCommandBindingExpression); if (!true.Equals(enabledValue)) link.SetValue(ButtonBase.EnabledProperty, enabledValue); @@ -295,14 +355,28 @@ protected virtual void SetNavigationButtonContent(IDotvvmRequestContext context, } } - protected virtual void SetPageNumberSpanContent(Literal notLink, DataPagerBindings pagerBindings, IDotvvmRequestContext context) + protected virtual void SetPageNumberSpanContent(IDotvvmRequestContext context, HtmlGenericControl span, DataPagerBindings pagerBindings, ITemplate? userDefinedContentTemplate) { - notLink.SetBinding(Literal.TextProperty, pagerBindings.PageNumberText.NotNull()); + if (userDefinedContentTemplate != null) + { + userDefinedContentTemplate.BuildContent(context, span); + } + else + { + span.SetBinding(Literal.TextProperty, pagerBindings.PageNumberText.NotNull()); + } } - protected virtual void SetPageNumberButtonContent(LinkButton link, DataPagerBindings pagerBindings, IDotvvmRequestContext context) + protected virtual void SetPageNumberButtonContent(IDotvvmRequestContext context, LinkButton link, DataPagerBindings pagerBindings, ITemplate? userDefinedContentTemplate) { - link.SetBinding(ButtonBase.TextProperty, pagerBindings.PageNumberText.NotNull()); + if (userDefinedContentTemplate != null) + { + userDefinedContentTemplate.BuildContent(context, link); + } + else + { + link.SetBinding(ButtonBase.TextProperty, pagerBindings.PageNumberText.NotNull()); + } } protected virtual void AddItemCssClass(HtmlGenericControl item, IDotvvmRequestContext context) diff --git a/src/Samples/Common/ViewModels/ControlSamples/DataPager/DataPagerTemplatesViewModel.cs b/src/Samples/Common/ViewModels/ControlSamples/DataPager/DataPagerTemplatesViewModel.cs new file mode 100644 index 0000000000..b8f1ce2a04 --- /dev/null +++ b/src/Samples/Common/ViewModels/ControlSamples/DataPager/DataPagerTemplatesViewModel.cs @@ -0,0 +1,55 @@ +using DotVVM.Framework.Controls; +using DotVVM.Framework.ViewModel; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace DotVVM.Samples.BasicSamples.ViewModels.ControlSamples.DataPager +{ + public class DataPagerTemplatesViewModel : DotvvmViewModelBase + { + public GridViewDataSet DataSet { get; set; } + + public string[] RomanNumerals { get; set; } = new[] { "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII", "XIII", "XIV", "XV", "XVI", "XVII", "XVIII", "XIX", "XX" }; + + public override Task Init() + { + DataSet = new GridViewDataSet() + { + PagingOptions = new PagingOptions() + { + PageSize = 3 + } + }; + return base.Init(); + } + + public override Task PreRender() + { + if (DataSet.IsRefreshRequired) + { + DataSet.LoadFromQueryable(FakeDB(50)); + } + + return base.PreRender(); + } + + private IQueryable FakeDB(int itemsCreatorCounter) + { + var dbdata = new List(); + for (var i = 0; i < itemsCreatorCounter; i++) + { + dbdata.Add(new Data + { + Text = $"Item {i}" + }); + } + return dbdata.AsQueryable(); + } + + public class Data + { + public string Text { get; set; } + } + } +} diff --git a/src/Samples/Common/ViewModels/ControlSamples/DataPager/DataPagerViewModel.cs b/src/Samples/Common/ViewModels/ControlSamples/DataPager/DataPagerViewModel.cs index 72144c08a1..7c05459bbd 100644 --- a/src/Samples/Common/ViewModels/ControlSamples/DataPager/DataPagerViewModel.cs +++ b/src/Samples/Common/ViewModels/ControlSamples/DataPager/DataPagerViewModel.cs @@ -10,6 +10,8 @@ public class DataPagerViewModel : DotvvmViewModelBase { public GridViewDataSet DataSet { get; set; } + public string[] RomanNumerals { get; set; } = new[] { "", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII", "XIII", "XIV", "XV", "XVI", "XVII", "XVIII", "XIX", "XX" }; + public bool Enabled { get; set; } = true; public int ItemsInDatabaseCount { get; set; } = 2; diff --git a/src/Samples/Common/Views/ControlSamples/DataPager/DataPagerTemplates.dothtml b/src/Samples/Common/Views/ControlSamples/DataPager/DataPagerTemplates.dothtml new file mode 100644 index 0000000000..65c7b6fbd6 --- /dev/null +++ b/src/Samples/Common/Views/ControlSamples/DataPager/DataPagerTemplates.dothtml @@ -0,0 +1,52 @@ +@viewModel DotVVM.Samples.BasicSamples.ViewModels.ControlSamples.DataPager.DataPagerTemplatesViewModel, DotVVM.Samples.Common + + + + + + + + + + + +

Templates in DataPager

+ + + +
  • {{value: Text}}
  • +
    +
    + + + ◀️◀️ + ◀️ + ▶️ + ▶️▶️ + + {{value: _root.RomanNumerals[_this]}} + + + + + + + diff --git a/src/Samples/Tests/Abstractions/SamplesRouteUrls.designer.cs b/src/Samples/Tests/Abstractions/SamplesRouteUrls.designer.cs index 34676c8fff..d962e32e67 100644 --- a/src/Samples/Tests/Abstractions/SamplesRouteUrls.designer.cs +++ b/src/Samples/Tests/Abstractions/SamplesRouteUrls.designer.cs @@ -76,6 +76,7 @@ public partial class SamplesRouteUrls public const string ControlSamples_ContentPlaceHolder_ContentPlaceHolderPage_ContentTest = "ControlSamples/ContentPlaceHolder/ContentPlaceHolderPage_ContentTest"; public const string ControlSamples_ContentPlaceHolder_DoubleContentPlaceHolderPage_ContentTest = "ControlSamples/ContentPlaceHolder/DoubleContentPlaceHolderPage_ContentTest"; public const string ControlSamples_DataPager_DataPager = "ControlSamples/DataPager/DataPager"; + public const string ControlSamples_DataPager_DataPagerTemplates = "ControlSamples/DataPager/DataPagerTemplates"; public const string ControlSamples_EnabledProperty_EnabledProperty = "ControlSamples/EnabledProperty/EnabledProperty"; public const string ControlSamples_EnvironmentView_EnvironmentViewTest = "ControlSamples/EnvironmentView/EnvironmentViewTest"; public const string ControlSamples_FileUpload_FileSize = "ControlSamples/FileUpload/FileSize"; diff --git a/src/Samples/Tests/Tests/Control/DataPagerTests.cs b/src/Samples/Tests/Tests/Control/DataPagerTests.cs index aadf996cbb..f5007bd97e 100644 --- a/src/Samples/Tests/Tests/Control/DataPagerTests.cs +++ b/src/Samples/Tests/Tests/Control/DataPagerTests.cs @@ -295,5 +295,27 @@ IElementWrapper GetPageIndex(int index) CheckNearPageIndexes(Enumerable.Range(11, 7)); }); } + + [Fact] + public void Control_DataPager_DataPagerTemplates() + { + RunInAllBrowsers(browser => { + browser.NavigateToUrl(SamplesRouteUrls.ControlSamples_DataPager_DataPagerTemplates); + + var pager = browser.Single(".pagination"); + + var items = pager.FindElements(".page-item"); + items.ThrowIfDifferentCountThan(10); + + var content = new[] { "◀️◀️", "◀️", "I", "II", "III", "IV", "V", "VI", "▶️", "▶️▶️" }; + for (var i = 0; i < items.Count; i++) + { + var item = items[i]; + + var link = item.Single(".page-link"); + AssertUI.TextEquals(link, content[i]); + } + }); + } } } From 684d10896fc09845577aacb055518d2d13ff5825 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Herceg?= Date: Fri, 12 Jun 2026 13:19:01 +0200 Subject: [PATCH 2/3] Warnings fixed, UI test updated to indicate repair of HtmlWriter bug --- src/Framework/Framework/Controls/DataPager.cs | 8 +++----- .../ControlSamples/DataPager/DataPagerTemplates.dothtml | 4 +++- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Framework/Framework/Controls/DataPager.cs b/src/Framework/Framework/Controls/DataPager.cs index d0674fad66..eebf612837 100644 --- a/src/Framework/Framework/Controls/DataPager.cs +++ b/src/Framework/Framework/Controls/DataPager.cs @@ -21,7 +21,6 @@ namespace DotVVM.Framework.Controls public class DataPager : HtmlGenericControl { private readonly GridViewDataSetBindingProvider gridViewDataSetBindingProvider; - private readonly BindingCompilationService bindingCompilationService; private DataPagerBindings? pagerBindings; @@ -30,7 +29,6 @@ public DataPager(GridViewDataSetBindingProvider gridViewDataSetBindingProvider, : base("ul", false) { this.gridViewDataSetBindingProvider = gridViewDataSetBindingProvider; - this.bindingCompilationService = bindingCompilationService; } /// @@ -179,7 +177,7 @@ public ICommandBinding? LoadData [MarkupOptions(AllowBinding = false)] public string ActiveItemCssClass { - get { return (string)GetValue(ActiveItemCssClassProperty); } + get { return (string)GetValue(ActiveItemCssClassProperty)!; } set { SetValue(ActiveItemCssClassProperty, value); } } public static readonly DotvvmProperty ActiveItemCssClassProperty @@ -191,7 +189,7 @@ public static readonly DotvvmProperty ActiveItemCssClassProperty [MarkupOptions(AllowBinding = false)] public string DisabledItemCssClass { - get { return (string)GetValue(DisabledItemCssClassProperty); } + get { return (string)GetValue(DisabledItemCssClassProperty)!; } set { SetValue(DisabledItemCssClassProperty, value); } } public static readonly DotvvmProperty DisabledItemCssClassProperty @@ -363,7 +361,7 @@ protected virtual void SetPageNumberSpanContent(IDotvvmRequestContext context, H } else { - span.SetBinding(Literal.TextProperty, pagerBindings.PageNumberText.NotNull()); + span.SetBinding(HtmlGenericControl.InnerTextProperty, pagerBindings.PageNumberText.NotNull()); } } diff --git a/src/Samples/Common/Views/ControlSamples/DataPager/DataPagerTemplates.dothtml b/src/Samples/Common/Views/ControlSamples/DataPager/DataPagerTemplates.dothtml index 65c7b6fbd6..c8475c02b5 100644 --- a/src/Samples/Common/Views/ControlSamples/DataPager/DataPagerTemplates.dothtml +++ b/src/Samples/Common/Views/ControlSamples/DataPager/DataPagerTemplates.dothtml @@ -14,6 +14,8 @@ } .page-item { margin: 0 1em; + padding: 1em; + border: solid 1px black; } .page-link { text-decoration: none; @@ -35,7 +37,7 @@ ◀️◀️ ◀️ From abe1e119f9b313ce914e8f50f10f3d161da59793 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Herceg?= Date: Fri, 12 Jun 2026 14:47:33 +0200 Subject: [PATCH 3/3] Test fixes --- .../DataPager/DataPagerTemplates.dothtml | 2 +- ...alizationTests.SerializeDefaultConfig.json | 97 +++++++++++++++++++ 2 files changed, 98 insertions(+), 1 deletion(-) diff --git a/src/Samples/Common/Views/ControlSamples/DataPager/DataPagerTemplates.dothtml b/src/Samples/Common/Views/ControlSamples/DataPager/DataPagerTemplates.dothtml index c8475c02b5..20dd42cf62 100644 --- a/src/Samples/Common/Views/ControlSamples/DataPager/DataPagerTemplates.dothtml +++ b/src/Samples/Common/Views/ControlSamples/DataPager/DataPagerTemplates.dothtml @@ -37,7 +37,7 @@ ◀️◀️ ◀️ diff --git a/src/Tests/Runtime/config-tests/ConfigurationSerializationTests.SerializeDefaultConfig.json b/src/Tests/Runtime/config-tests/ConfigurationSerializationTests.SerializeDefaultConfig.json index 24fbd31f18..5d893cd5ce 100644 --- a/src/Tests/Runtime/config-tests/ConfigurationSerializationTests.SerializeDefaultConfig.json +++ b/src/Tests/Runtime/config-tests/ConfigurationSerializationTests.SerializeDefaultConfig.json @@ -550,11 +550,21 @@ } }, "DotVVM.Framework.Controls.DataPager": { + "ActiveItemCssClass": { + "type": "System.String", + "defaultValue": "active", + "onlyHardcoded": true + }, "DataSet": { "type": "DotVVM.Framework.Controls.IPageableGridViewDataSet`1[[DotVVM.Framework.Controls.IPagingOptions, DotVVM.Core, Version=***, Culture=neutral, PublicKeyToken=23f3607db32275da]], DotVVM.Core", "required": true, "onlyBindings": true }, + "DisabledItemCssClass": { + "type": "System.String", + "defaultValue": "disabled", + "onlyHardcoded": true + }, "Enabled": { "type": "System.Boolean", "defaultValue": true @@ -574,6 +584,24 @@ "mappingMode": "InnerElement", "onlyHardcoded": true }, + "LinkID": { + "type": "System.String", + "fromCapability": "LinkHtmlCapability" + }, + "LinkVisible": { + "type": "System.Boolean", + "defaultValue": true, + "fromCapability": "LinkHtmlCapability" + }, + "ListItemID": { + "type": "System.String", + "fromCapability": "ListItemHtmlCapability" + }, + "ListItemVisible": { + "type": "System.Boolean", + "defaultValue": true, + "fromCapability": "ListItemHtmlCapability" + }, "LoadData": { "type": "DotVVM.Framework.Binding.Expressions.ICommandBinding, DotVVM.Framework", "onlyBindings": true @@ -583,6 +611,27 @@ "mappingMode": "InnerElement", "onlyHardcoded": true }, + "PageNumberTemplate": { + "type": "DotVVM.Framework.Controls.ITemplate, DotVVM.Framework", + "dataContextChange": [ + { + "$type": "DotVVM.Framework.Binding.ConstantDataContextChangeAttribute", + "Type": "System.Int32[]", + "Order": 0, + "ServerSideOnly": null, + "NestDataContext": true, + "PropertyDependsOn": [] + }, + { + "$type": "DotVVM.Framework.Binding.CollectionElementDataContextChangeAttribute", + "Order": 1, + "NestDataContext": true, + "PropertyDependsOn": [] + } + ], + "mappingMode": "InnerElement", + "onlyHardcoded": true + }, "PreviousPageTemplate": { "type": "DotVVM.Framework.Controls.ITemplate, DotVVM.Framework", "mappingMode": "InnerElement", @@ -1823,6 +1872,16 @@ "type": "DotVVM.Framework.Controls.TextOrContentCapability, DotVVM.Framework" } }, + "DotVVM.Framework.Controls.DataPager": { + "LinkHtmlCapability": { + "type": "DotVVM.Framework.Controls.HtmlCapability, DotVVM.Framework", + "capabilityPrefix": "Link" + }, + "ListItemHtmlCapability": { + "type": "DotVVM.Framework.Controls.HtmlCapability, DotVVM.Framework", + "capabilityPrefix": "ListItem" + } + }, "DotVVM.Framework.Controls.HierarchyRepeater": { "ItemHtmlCapability": { "type": "DotVVM.Framework.Controls.HtmlCapability, DotVVM.Framework", @@ -1957,6 +2016,44 @@ "fromCapability": "FieldSelectorProps" } }, + "DotVVM.Framework.Controls.DataPager": { + "LinkAttributes": { + "prefixes": [ + "Link", + "Linkhtml:" + ], + "type": "System.Object", + "fromCapability": "LinkHtmlCapability" + }, + "LinkCssClasses": { + "prefix": "LinkClass-", + "type": "System.Boolean", + "fromCapability": "LinkHtmlCapability" + }, + "LinkCssStyles": { + "prefix": "LinkStyle-", + "type": "System.Object", + "fromCapability": "LinkHtmlCapability" + }, + "ListItemAttributes": { + "prefixes": [ + "ListItem", + "ListItemhtml:" + ], + "type": "System.Object", + "fromCapability": "ListItemHtmlCapability" + }, + "ListItemCssClasses": { + "prefix": "ListItemClass-", + "type": "System.Boolean", + "fromCapability": "ListItemHtmlCapability" + }, + "ListItemCssStyles": { + "prefix": "ListItemStyle-", + "type": "System.Object", + "fromCapability": "ListItemHtmlCapability" + } + }, "DotVVM.Framework.Controls.HierarchyRepeater": { "ItemAttributes": { "prefixes": [