Skip to content
Shiny Controls v1.0 - The Ultra Control Suite for .NET MAUI & BlazorO...M...G!

Sections & Dynamic Content

Sections group cells together with optional headers and footers. They also support generating cells dynamically from data sources.

The basic building block for organizing cells into groups.

<tv:TableSection Title="GENERAL"
FooterText="These settings apply globally">
<tv:LabelCell Title="Item 1" />
<tv:LabelCell Title="Item 2" />
</tv:TableSection>
Property Type Default Description
Title string "" Section header text
FooterText string "" Section footer text
HeaderView View? null Custom header view (overrides Title)
FooterView View? null Custom footer view (overrides FooterText)
IsVisible bool true Show/hide entire section
FooterVisible bool true Show/hide footer only
UseDragSort bool false Add a drag handle to each row for reordering
Property Type Default Description
HeaderBackgroundColor Color? null Header background
HeaderTextColor Color? null Header text color
HeaderFontSize double -1 Header font size
HeaderFontFamily string? null Header font family
HeaderFontAttributes FontAttributes? null Header styling (Bold, Italic, None)
HeaderHeight double -1 Fixed header height
Property Type Default Description
FooterTextColor Color? null Footer text color
FooterFontSize double -1 Footer font size
FooterBackgroundColor Color? null Footer background

Replace the default text header or footer with any MAUI view:

<tv:TableSection>
<tv:TableSection.HeaderView>
<HorizontalStackLayout Padding="16,8" Spacing="8">
<Image Source="settings_icon.png" HeightRequest="20" />
<Label Text="PREFERENCES"
FontAttributes="Bold"
VerticalOptions="Center" />
</HorizontalStackLayout>
</tv:TableSection.HeaderView>
<tv:SwitchCell Title="Notifications" On="{Binding Notifications}" />
<tv:TableSection.FooterView>
<Label Text="Manage how you receive alerts"
Padding="16,4"
FontSize="12"
TextColor="Gray" />
</tv:TableSection.FooterView>
</tv:TableSection>

Sections can generate cells dynamically from a data source. The section observes INotifyCollectionChanged for live add/remove updates.

<tv:TableSection Title="Tasks"
ItemsSource="{Binding Tasks}">
<tv:TableSection.ItemTemplate>
<DataTemplate>
<tv:CheckboxCell Title="{Binding Name}"
Checked="{Binding IsComplete, Mode=TwoWay}" />
</DataTemplate>
</tv:TableSection.ItemTemplate>
</tv:TableSection>
Property Type Default Description
ItemsSource IEnumerable? null Data source for generated cells
ItemTemplate DataTemplate? null Template for each item
TemplateStartIndex int 0 Insert position among static cells

Use TemplateStartIndex to control where dynamic cells are inserted among static cells:

<tv:TableSection Title="Items"
ItemsSource="{Binding Items}"
TemplateStartIndex="1">
<!-- Static cell at index 0 (always first) -->
<tv:CommandCell Title="Add New Item"
Command="{Binding AddItemCommand}" />
<!-- ItemTemplate cells inserted starting at index 1 -->
<tv:TableSection.ItemTemplate>
<DataTemplate>
<tv:LabelCell Title="{Binding Name}"
ValueText="{Binding Value}" />
</DataTemplate>
</tv:TableSection.ItemTemplate>
</tv:TableSection>

The TableView itself supports generating entire sections from a data source:

<tv:TableView ItemsSource="{Binding Categories}">
<tv:TableView.ItemTemplate>
<DataTemplate>
<tv:TableSection Title="{Binding CategoryName}">
<tv:LabelCell Title="{Binding Description}" />
</tv:TableSection>
</DataTemplate>
</tv:TableView.ItemTemplate>
<tv:TableRoot>
<!-- Static sections can coexist with dynamic ones -->
<tv:TableSection Title="Static Section">
<tv:LabelCell Title="Always visible" />
</tv:TableSection>
</tv:TableRoot>
</tv:TableView>

Show or hide sections and footers dynamically:

<tv:TableSection Title="Advanced"
IsVisible="{Binding ShowAdvanced}"
FooterText="These options are for power users"
FooterVisible="{Binding ShowFooter}">
<tv:EntryCell Title="Custom Server"
ValueText="{Binding CustomServer, Mode=TwoWay}" />
</tv:TableSection>

Setting IsVisible="False" hides the entire section including header, cells, and footer — and its section separators, so the sections either side of it close up rather than leaving a doubled rule or a stray line under the last visible section. Setting FooterVisible="False" hides only the footer while keeping the rest visible.

IsVisible is live: flipping it re-renders the table, so binding it to a feature flag or a mode switch is the intended use.