Attached Properties

July 14, 2026 · View on GitHub

Attached properties are defined on one type but set on instances of other types — Grid.Row, Shell.TitleColor, SemanticProperties.Hint, and so on. FmgLib.MauiMarkup maps each one to a fluent method so they read like normal properties.

Quick Example

// XAML:  <Border AbsoluteLayout.LayoutBounds="100,100,200,200" />
new Border().AbsoluteLayoutBounds(new Rect(100, 100, 200, 200));

// convenience overload without constructing a Rect:
new Border().AbsoluteLayoutBounds(100, 100, 200, 200);

Complete Mapping Table

Grid

MAUI attached propertyFluent method
Grid.ColumnColumn()
Grid.RowRow()
Grid.ColumnSpanColumnSpan()
Grid.RowSpanRowSpan()
Grid.ColumnSpan + Grid.RowSpanGridSpan(column, row)
new Image().Row(0).Column(1).RowSpan(2)

AbsoluteLayout

MAUI attached propertyFluent method
AbsoluteLayout.LayoutFlagsAbsoluteLayoutFlags()
AbsoluteLayout.LayoutBoundsAbsoluteLayoutBounds()
new AbsoluteLayout().Children(
    new BoxView()
        .Color(Colors.Teal)
        .AbsoluteLayoutFlags(AbsoluteLayoutFlags.PositionProportional)
        .AbsoluteLayoutBounds(new Rect(0.5, 0.5, 100, 100))   // centered, 100×100
)

BindableLayout (on any layout)

MAUI attached propertyFluent method
BindableLayout.ItemsSourceBindableLayoutItemsSource()
BindableLayout.ItemTemplateBindableLayoutItemTemplate()
BindableLayout.TemplateSelectorBindableItemTemplateSelector()
BindableLayout.EmptyViewBindableLayoutEmptyView()
BindableLayout.EmptyViewTemplateBindableLayoutEmptyViewTemplate()

See Collections & Templates for full examples.

RadioButton groups

MAUI attached propertyFluent method
RadioButtonGroup.GroupNameRadioButtonGroupGroupName()
RadioButtonGroup.SelectedValueRadioButtonGroupSelectedValue()
new VerticalStackLayout()
    .RadioButtonGroupGroupName("Sizes")
    .RadioButtonGroupSelectedValue(e => e.Path("SelectedSize").BindingMode(BindingMode.TwoWay))
    .Children(
        new RadioButton().Content("S").Value("S"),
        new RadioButton().Content("M").Value("M"),
        new RadioButton().Content("L").Value("L")
    )

Flyout / context menus

MAUI attached propertyFluent method
FlyoutBase.ContextFlyoutContextFlyout()

See Menus.

VisualStateManager

MAUI attached propertyFluent method
VisualStateManager.VisualStateGroupsVisualStateGroups()

See Visual States.

Shell (set on pages/items)

MAUI attached propertyFluent method
Shell.PresentationModeShellPresentationMode()
Shell.BackgroundColorShellBackgroundColor()
Shell.ForegroundColorShellForegroundColor()
Shell.TitleColorShellTitleColor()
Shell.DisabledColorShellDisabledColor()
Shell.UnselectedColorShellUnselectedColor()
Shell.NavBarHasShadowShellNavBarHasShadow()
Shell.NavBarIsVisibleShellNavBarIsVisible()
Shell.TitleViewShellTitleView()
Shell.TabBarBackgroundColorShellTabBarBackgroundColor()
Shell.TabBarForegroundColorShellTabBarForegroundColor()
Shell.TabBarTitleColorShellTabBarTitleColor()
Shell.TabBarDisabledColorShellTabBarDisabledColor()
Shell.TabBarUnselectedColorShellTabBarUnselectedColor()
Shell.TabBarIsVisibleShellTabBarIsVisible()
Shell.FlyoutBackdropShellFlyoutBackdrop()
Shell.FlyoutBehaviorShellFlyoutBehavior()
Shell.FlyoutHeightShellFlyoutHeight()
Shell.FlyoutWidthShellFlyoutWidth()
Shell.FlyoutItemIsVisibleShellFlyoutItemIsVisible()
Shell.BackButtonBehaviorShellBackButtonBehavior()
Shell.ItemTemplateShellItemTemplate()
Shell.MenuItemTemplateShellMenuItemTemplate()
Shell.SearchHandlerShellSearchHandler()

Example — hide the nav bar and tab bar on a login page:

public partial class LoginPage : ContentPage, IFmgLibHotReload
{
    public LoginPage() => this.InitializeHotReload();

    public void Build() =>
        this
        .ShellNavBarIsVisible(false)
        .ShellTabBarIsVisible(false)
        .Content(/* ... */);
}
MAUI attached propertyFluent method
NavigationPage.HasNavigationBarNavigationPageHasNavigationBar()
NavigationPage.BackButtonTitleNavigationPageBackButtonTitle()
NavigationPage.HasBackButtonNavigationPageHasBackButton()
NavigationPage.IconColorNavigationPageIconColor()
NavigationPage.TitleIconImageSourceNavigationPageTitleIconImageSource()
NavigationPage.TitleViewNavigationPageTitleView()

Accessibility — Semantic & Automation

MAUI attached propertyFluent method
SemanticProperties.HintSemanticHint()
SemanticProperties.DescriptionSemanticDescription()
SemanticProperties.HeadingLevelSemanticHeadingLevel()
AutomationProperties.ExcludedWithChildrenAutomationExcludedWithChildren()
AutomationProperties.IsInAccessibleTreeAutomationIsInAccessibleTree()
AutomationProperties.NameAutomationName()
AutomationProperties.HelpTextAutomationHelpText()
AutomationProperties.LabeledByAutomationLabeledBy()
new Image()
    .Source("logo.png")
    .SemanticDescription("Company logo")
    .SemanticHint("Decorative image at the top of the page")

new Label()
    .Text("Settings")
    .SemanticHeadingLevel(SemanticHeadingLevel.Level1)

Tooltips

MAUI attached propertyFluent method
ToolTipProperties.TextToolTipPropertiesText()
new Button().Text("?").ToolTipPropertiesText("Opens the help center")

Naming Convention

The rule of thumb for guessing a method name:

  • Grid placement drops the owner prefix: Grid.RowRow().
  • Everything else concatenates owner + property: Shell.TitleColorShellTitleColor(), SemanticProperties.HintSemanticHint(), AutomationProperties.NameAutomationName().

The same convention is used for third-party attached properties generated by [MauiMarkupAttachedProp] — e.g. InputKit's FormView.IsSubmitButton becomes FormViewIsSubmitButton().

Builder Support

Attached-property methods accept the property builder lambda like any other property, so bindings and theme/platform values work:

new ContentPage()
    .ShellTabBarIsVisible(e => e.Path("IsTabBarVisible"))
    .ShellBackgroundColor(e => e.OnLight(Colors.White).OnDark(Colors.Black))