Blazorise PropertyGrid component

Display and edit related values in a compact inspector with grouping, sorting, search, and contextual help.

Overview

A property grid presents a large set of editable values without the space and visual weight of a conventional form. It is well suited to designer surfaces, object inspectors, settings panels, and other interfaces where users need to review and adjust many related options.

Each property is displayed as a label and editor row, with related properties organized into collapsible groups. Properties can be searched or arranged by category or name, while optional row actions and descriptions provide additional behavior and guidance without crowding the editor.

Structure

  • <PropertyGrid> is the main container for a manually composed property grid.

    • <PropertyGridToolbar> is the container for commands and search controls.

      • <PropertyGridToolbarButton> is a toolbar command, such as switching the property view mode.

      • <PropertyGridToolbarSearch> is a search input that captures property filter text.

    • <PropertyGridGroup> is an expandable group of related property rows.

      • <PropertyGridItem> is a property row with a label, editor content, and optional action.

      • <PropertyGridTextItem>, <PropertyGridBooleanItem>, PropertyGridNumericItem<TValue>, PropertyGridSelectItem<TValue>, <PropertyGridStringSelectItem>, and <PropertyGridColorItem> are ready-to-use property rows for common value types.

    • <PropertyGridHelp> is the panel that displays the selected property's name and description.

  • <PropertyGridView> is a higher-level component that builds the toolbar, groups, rows, and help panel from a PropertyGridSchema.

Choosing an approach

Use <PropertyGrid> for a fixed set of properties known in Razor markup. Compose its toolbar, groups, editors, and help panel directly, and bind each editor to the corresponding value. This approach gives you full control over which components are rendered and how filtering is applied.

Use <PropertyGridView> when properties are dynamic or supplied by application metadata. A PropertyGridSchema describes the groups, editor types, values, descriptions, and actions, while the view builds the complete property grid. Handle PropertyValueChanged using the stable property key, update the backing model, and provide a new schema when displayed values change.

Give either component a constrained Height to keep large property sets inside an independently scrolling viewport. The toolbar remains visible while properties scroll, and selecting a property shows its Description in the help panel. Property groups and rows include the grid, selection, and expansion semantics needed by assistive technologies.

Examples

Basic

Use manual composition when the available properties are known in advance. This example binds editor components directly, supplies a complete reset button through ActionContent, adds search in the toolbar, and filters the rendered rows in Razor.

Current values: Quarterly summary, 640 x 360 px, Arial 16 px, Left, Blue, visible

<PropertyGrid Width="Width.Px( 360 )">
    <Toolbar>
        <PropertyGridToolbar>
            <PropertyGridToolbarButton Icon="IconName.Clear"
                                       Title="Clear search"
                                       Disabled="@( string.IsNullOrWhiteSpace( searchText ) )"
                                       Clicked="@ClearSearch" />
            <PropertyGridToolbarSearch @bind-SearchText="@searchText" />
        </PropertyGridToolbar>
    </Toolbar>
    <ChildContent>
        <PropertyGridGroup Title="Appearance">
            @if ( MatchesSearch( "Title" ) )
            {
                <PropertyGridTextItem Label="Title" @bind-Value="@title">
                    <ActionContent>
                        <Button Color="Color.Light"
                                Size="Size.Small"
                                Clicked="@ResetTitle"
                                title="Reset title"
                                aria-label="Reset title">
                            <Icon Name="IconName.Undo" />
                        </Button>
                    </ActionContent>
                </PropertyGridTextItem>
            }
            @if ( MatchesSearch( "Visible" ) )
            {
                <PropertyGridBooleanItem Label="Visible" @bind-Value="@visible" TrueText="Visible" FalseText="Hidden" />
            }
            @if ( MatchesSearch( "Accent" ) )
            {
                <PropertyGridColorItem Label="Accent" @bind-Value="@accent" />
            }
        </PropertyGridGroup>
        <PropertyGridGroup Title="Typography">
            @if ( MatchesSearch( "Font family" ) )
            {
                <PropertyGridStringSelectItem Label="Font family" @bind-Value="@fontFamily" Options="@fontFamilyOptions" />
            }
            @if ( MatchesSearch( "Font size" ) )
            {
                <PropertyGridNumericItem TValue="int" Label="Font size" @bind-Value="@fontSize" Min="8" Max="72" />
            }
            @if ( MatchesSearch( "Bold" ) )
            {
                <PropertyGridBooleanItem Label="Bold" @bind-Value="@bold" />
            }
            @if ( MatchesSearch( "Italic" ) )
            {
                <PropertyGridBooleanItem Label="Italic" @bind-Value="@italic" />
            }
        </PropertyGridGroup>
        <PropertyGridGroup Title="Layout">
            @if ( MatchesSearch( "Width" ) )
            {
                <PropertyGridNumericItem TValue="int" Label="Width" @bind-Value="@width" Min="100" Max="1200" Step="10" />
            }
            @if ( MatchesSearch( "Height" ) )
            {
                <PropertyGridNumericItem TValue="int" Label="Height" @bind-Value="@height" Min="100" Max="1200" Step="10" />
            }
            @if ( MatchesSearch( "Padding" ) )
            {
                <PropertyGridNumericItem TValue="int" Label="Padding" @bind-Value="@padding" Min="0" Max="64" />
            }
            @if ( MatchesSearch( "Alignment" ) )
            {
                <PropertyGridStringSelectItem Label="Alignment" @bind-Value="@alignment" Options="@alignmentOptions" />
            }
        </PropertyGridGroup>
    </ChildContent>
    <Help>
        <PropertyGridHelp Title="Manual composition"
                          Description="Toolbar, editor, filtering, and help behavior can be composed directly." />
    </Help>
</PropertyGrid>

<Paragraph Margin="Margin.Is3.FromTop">
    <Strong>Current values:</Strong>
    @title, @width x @height px, @fontFamily @fontSize px, @alignment, @accent, @(visible ? "visible" : "hidden")
</Paragraph>
@code {
    private static readonly IReadOnlyList<PropertyGridSelectOption<string>> alignmentOptions =
    [
        new( "Left", "Left" ),
        new( "Center", "Center" ),
        new( "Right", "Right" ),
    ];

    private static readonly IReadOnlyList<PropertyGridSelectOption<string>> fontFamilyOptions =
    [
        new( "Arial", "Arial" ),
        new( "Georgia", "Georgia" ),
        new( "Inter", "Inter" ),
    ];

    private string title = "Quarterly summary";

    private bool visible = true;

    private string accent = "Blue";

    private string fontFamily = "Arial";

    private int fontSize = 16;

    private bool bold;

    private bool italic;

    private int width = 640;

    private int height = 360;

    private int padding = 16;

    private string alignment = "Left";

    private string searchText;

    private bool MatchesSearch( string label )
        => string.IsNullOrWhiteSpace( searchText )
            || label.Contains( searchText, StringComparison.CurrentCultureIgnoreCase );

    private void ClearSearch()
        => searchText = string.Empty;

    private void ResetTitle()
        => title = "Quarterly summary";
}

Schema

Use a schema for property sets created at runtime. <PropertyGridView> renders the appropriate editors and reports changes by property key so the backing model can be updated.

Status: Change a property or invoke its action.

<PropertyGridView Width="Width.Px( 360 )"
                  Schema="@schema"
                  PropertyValueChanged="@OnPropertyValueChanged"
                  ActionInvoked="@OnActionInvoked"
                  @bind-SelectedProperty="@selectedProperty"
                  @bind-ViewMode="@viewMode" />

<Paragraph Margin="Margin.Is3.FromTop">
    <Strong>Status:</Strong> @status
    @if ( selectedProperty is not null )
    {
        <Span> Selected: @selectedProperty.Label.</Span>
    }
</Paragraph>
@code {
    private string documentName = "Quarterly report";

    private string documentDescription = "Quarterly financial performance.";

    private string category = "Finance";

    private bool enabled = true;

    private int pageWidth = 794;

    private int pageHeight = 1123;

    private string orientation = "Portrait";

    private int copies = 1;

    private string format = "PDF";

    private string accent = "Blue";

    private bool includePageNumbers = true;

    private string status = "Change a property or invoke its action.";

    private PropertyGridViewMode viewMode = PropertyGridViewMode.Categorized;

    private PropertyGridSchema schema;

    private PropertyGridProperty selectedProperty;

    protected override void OnInitialized()
    {
        schema = BuildSchema();
    }

    private PropertyGridSchema BuildSchema()
        => new(
        [
            new PropertyGridGroupDefinition(
                "document",
                "Document",
                [
                    new PropertyGridTextProperty( "document.name", "Name", documentName )
                    {
                        Description = "The display name used for the generated document.",
                        Immediate = true,
                        Action = new PropertyGridAction( "rename" )
                        {
                            Icon = IconName.Edit,
                            Title = "Rename document",
                        },
                    },
                    new PropertyGridBooleanProperty( "document.enabled", "Enabled", enabled )
                    {
                        Description = "Controls whether the document is included in output.",
                        TrueText = "Enabled",
                        FalseText = "Disabled",
                    },
                    new PropertyGridTextProperty( "document.description", "Description", documentDescription )
                    {
                        Description = "A short summary of the document contents.",
                        Immediate = true,
                    },
                    new PropertyGridStringSelectProperty(
                        "document.category",
                        "Category",
                        category,
                        [
                            new( "Finance", "Finance" ),
                            new( "Operations", "Operations" ),
                            new( "Sales", "Sales" ),
                        ] )
                    {
                        Description = "The category used to organize the document.",
                    },
                ] ),
            new PropertyGridGroupDefinition(
                "layout",
                "Layout",
                [
                    new PropertyGridNumericProperty<int>( "layout.width", "Page width", pageWidth )
                    {
                        Description = "The page width in pixels.",
                        Min = 100,
                        Max = 2000,
                    },
                    new PropertyGridNumericProperty<int>( "layout.height", "Page height", pageHeight )
                    {
                        Description = "The page height in pixels.",
                        Min = 100,
                        Max = 2000,
                    },
                    new PropertyGridStringSelectProperty(
                        "layout.orientation",
                        "Orientation",
                        orientation,
                        [
                            new( "Portrait", "Portrait" ),
                            new( "Landscape", "Landscape" ),
                        ] )
                    {
                        Description = "The page orientation used during export.",
                    },
                ] ),
            new PropertyGridGroupDefinition(
                "output",
                "Output",
                [
                    new PropertyGridStringSelectProperty(
                        "output.format",
                        "Format",
                        format,
                        [
                            new( "PDF", "PDF" ),
                            new( "HTML", "HTML" ),
                            new( "CSV", "CSV" ),
                        ] )
                    {
                        Description = "The file format used when the document is exported.",
                    },
                    new PropertyGridNumericProperty<int>( "output.copies", "Copies", copies )
                    {
                        Description = "The number of output copies to create.",
                        Min = 1,
                        Max = 10,
                    },
                    new PropertyGridColorProperty( "output.accent", "Accent", accent )
                    {
                        Description = "The accent color used by the document theme.",
                    },
                    new PropertyGridBooleanProperty( "output.pageNumbers", "Page numbers", includePageNumbers )
                    {
                        Description = "Controls whether page numbers are included in output.",
                        TrueText = "Included",
                        FalseText = "Hidden",
                    },
                ] ),
        ] );

    private void OnPropertyValueChanged( PropertyGridValueChangedEventArgs eventArgs )
    {
        switch ( eventArgs.PropertyKey )
        {
            case "document.name":
                documentName = eventArgs.GetValue<string>();
                break;
            case "document.enabled":
                enabled = eventArgs.GetValue<bool>();
                break;
            case "document.description":
                documentDescription = eventArgs.GetValue<string>();
                break;
            case "document.category":
                category = eventArgs.GetValue<string>();
                break;
            case "layout.width":
                pageWidth = eventArgs.GetValue<int>();
                break;
            case "layout.height":
                pageHeight = eventArgs.GetValue<int>();
                break;
            case "layout.orientation":
                orientation = eventArgs.GetValue<string>();
                break;
            case "output.format":
                format = eventArgs.GetValue<string>();
                break;
            case "output.copies":
                copies = eventArgs.GetValue<int>();
                break;
            case "output.accent":
                accent = eventArgs.GetValue<string>();
                break;
            case "output.pageNumbers":
                includePageNumbers = eventArgs.GetValue<bool>();
                break;
        }

        status = $"{eventArgs.Property.Label} changed.";
        schema = BuildSchema();
    }

    private void OnActionInvoked( PropertyGridActionEventArgs eventArgs )
    {
        status = $"{eventArgs.Action.Name} invoked for {eventArgs.Property.Label}.";
    }
}

Templates

Keep the schema-driven behavior while replacing selected parts of the UI. Templates can customize the toolbar, groups, rows, labels, editors, and actions, and their contexts provide the current definition and update callbacks.

Current item: Revenue, Card, 100% opacity

<PropertyGridView Width="Width.Px( 360 )"
                  Schema="@schema"
                  PropertyValueChanged="@OnPropertyValueChanged"
                  ActionInvoked="@OnActionInvoked"
                  ShowToolbar="false">
    <GroupHeaderTemplate Context="context">
        <Span Display="Display.Flex" Flex="Flex.AlignItems.Center" Gap="Gap.Is2">
            <Icon Name="IconName.Wrench" />
            <Strong>@context.Group.Title</Strong>
        </Span>
    </GroupHeaderTemplate>
    <LabelTemplate Context="context">
        <Strong>@context.Label</Strong>
    </LabelTemplate>
    <TextEditorTemplate Context="context">
        <TextInput Value="@( context.GetValue<string>() )"
                   ValueChanged="@( ( string value ) => context.SetValue( value ) )"
                   Size="Size.Small" />
    </TextEditorTemplate>
    <ActionTemplate Context="context">
        <Button Color="Color.Warning"
                Size="Size.Small"
                Title="@context.Action.Title"
                Clicked="@context.Invoke">
            @context.Action.Text
        </Button>
    </ActionTemplate>
    <HelpTemplate Context="context">
        <Strong>About @context.Label</Strong>
        <Text>@context.Description</Text>
    </HelpTemplate>
</PropertyGridView>

<Paragraph Margin="Margin.Is3.FromTop">
    <Strong>Current item:</Strong> @displayName, @layoutMode, @opacity% opacity
</Paragraph>
@code {
    private string displayName = "Revenue";

    private string subtitle = "Year-to-date";

    private bool highlighted = true;

    private bool visible = true;

    private string accent = "Blue";

    private int opacity = 100;

    private string layoutMode = "Card";

    private bool locked;

    private string notes = "Reviewed monthly.";

    private PropertyGridSchema schema;

    protected override void OnInitialized()
    {
        schema = BuildSchema();
    }

    private PropertyGridSchema BuildSchema()
        => new(
        [
            new PropertyGridGroupDefinition(
                "appearance",
                "Custom appearance",
                [
                    new PropertyGridTextProperty( "appearance.name", "Display name", displayName )
                    {
                        Description = "The name displayed to users.",
                        Immediate = true,
                        Action = new PropertyGridAction( "reset" )
                        {
                            Text = "Reset",
                            Title = "Reset display name",
                        },
                    },
                    new PropertyGridBooleanProperty( "appearance.highlighted", "Highlighted", highlighted )
                    {
                        Description = "Emphasizes the item in the rendered output.",
                    },
                    new PropertyGridTextProperty( "appearance.subtitle", "Subtitle", subtitle )
                    {
                        Description = "The supporting text displayed below the name.",
                        Immediate = true,
                    },
                    new PropertyGridBooleanProperty( "appearance.visible", "Visible", visible )
                    {
                        Description = "Controls whether the item is displayed.",
                    },
                    new PropertyGridColorProperty( "appearance.accent", "Accent", accent )
                    {
                        Description = "The accent color used to emphasize the item.",
                    },
                    new PropertyGridNumericProperty<int>( "appearance.opacity", "Opacity", opacity )
                    {
                        Description = "The item opacity as a percentage.",
                        Min = 0,
                        Max = 100,
                    },
                ] ),
            new PropertyGridGroupDefinition(
                "behavior",
                "Custom behavior",
                [
                    new PropertyGridStringSelectProperty(
                        "behavior.layout",
                        "Layout",
                        layoutMode,
                        [
                            new( "Card", "Card" ),
                            new( "Compact", "Compact" ),
                            new( "Expanded", "Expanded" ),
                        ] )
                    {
                        Description = "The layout used to present the item.",
                    },
                    new PropertyGridBooleanProperty( "behavior.locked", "Locked", locked )
                    {
                        Description = "Prevents the item from being repositioned.",
                    },
                    new PropertyGridTextProperty( "behavior.notes", "Notes", notes )
                    {
                        Description = "Additional information about the item.",
                        Immediate = true,
                    },
                ] ),
        ] );

    private void OnPropertyValueChanged( PropertyGridValueChangedEventArgs eventArgs )
    {
        switch ( eventArgs.PropertyKey )
        {
            case "appearance.name":
                displayName = eventArgs.GetValue<string>();
                break;
            case "appearance.subtitle":
                subtitle = eventArgs.GetValue<string>();
                break;
            case "appearance.highlighted":
                highlighted = eventArgs.GetValue<bool>();
                break;
            case "appearance.visible":
                visible = eventArgs.GetValue<bool>();
                break;
            case "appearance.accent":
                accent = eventArgs.GetValue<string>();
                break;
            case "appearance.opacity":
                opacity = eventArgs.GetValue<int>();
                break;
            case "behavior.layout":
                layoutMode = eventArgs.GetValue<string>();
                break;
            case "behavior.locked":
                locked = eventArgs.GetValue<bool>();
                break;
            case "behavior.notes":
                notes = eventArgs.GetValue<string>();
                break;
        }

        schema = BuildSchema();
    }

    private void OnActionInvoked( PropertyGridActionEventArgs eventArgs )
    {
        if ( eventArgs.Action.Name != "reset" )
            return;

        displayName = "Revenue";
        schema = BuildSchema();
    }
}

API

Parameters

PropertyGrid

Parameter Description TypeDefault
AriaLabel

Defines the accessible property grid label.

string"Properties"
ChildContent

Specifies the property groups to be rendered inside this PropertyGrid.

RenderFragmentnull
Help

Specifies content rendered below the scrollable property viewport.

RenderFragmentnull
Toolbar

Specifies content rendered above the scrollable property viewport.

RenderFragmentnull

PropertyGridView

Parameter Description TypeDefault
ActionTemplate

Defines an action template.

RenderFragment<PropertyGridActionContext>null
AlphabeticalButtonIcon

Gets or sets the alphabetical button icon.

IconNameIconName.SortAlphaDown
AlphabeticalButtonTemplate

Defines the alphabetical view button template.

RenderFragment<PropertyGridViewModeContext>null
AlphabeticalButtonTitle

Gets or sets the alphabetical button title.

string"Alphabetical"
AriaLabel

Gets or sets the accessible property grid label.

string"Properties"
BooleanEditorTemplate

Defines a boolean editor template.

RenderFragment<PropertyGridEditorContext>null
CategorizedButtonIcon

Gets or sets the categorized button icon.

IconNameIconName.List
CategorizedButtonTemplate

Defines the categorized view button template.

RenderFragment<PropertyGridViewModeContext>null
CategorizedButtonTitle

Gets or sets the categorized button title.

string"Categorized"
ChildContent

Defines content rendered after all schema groups.

RenderFragmentnull
ColorEditorTemplate

Defines a color editor template.

RenderFragment<PropertyGridEditorContext>null
EmptyTemplate

Defines content rendered when the schema and child content are empty.

RenderFragmentnull
GroupHeaderTemplate

Defines a group header template.

RenderFragment<PropertyGridGroupContext>null
GroupTemplate

Defines a complete group template.

RenderFragment<PropertyGridGroupContext>null
HelpTemplate

Defines the selected property help template.

RenderFragment<PropertyGridHelpContext>null
ItemTemplate

Defines a complete property item template.

RenderFragment<PropertyGridItemContext>null
LabelTemplate

Defines a property label template.

RenderFragment<PropertyGridLabelContext>null
NoResultsTemplate

Defines content rendered when no properties match the current search.

RenderFragmentnull
NoResultsText

Defines the text rendered when no properties match the current search.

string"No properties found."
NumericEditorTemplate

Defines a numeric editor template.

RenderFragment<PropertyGridEditorContext>null
Schema

Gets or sets the schema rendered by the property grid.

PropertyGridSchemanull
SearchAriaLabel

Gets or sets the accessible property search label.

string"Search properties"
SearchDebounce

Gets or sets whether property search changes are debounced.

booltrue
SearchDebounceInterval

Gets or sets the property search debounce interval in milliseconds.

int300
SearchPlaceholder

Gets or sets the property search placeholder.

string"Search"
SearchTemplate

Defines the property search template.

RenderFragment<PropertyGridSearchContext>null
SearchText

Gets or sets the property search text.

string
SelectEditorTemplate

Defines a select editor template.

RenderFragment<PropertyGridEditorContext>null
SelectedProperty

Gets or sets the selected property.

PropertyGridPropertynull
ShowHelp

Gets or sets whether help for the selected property is shown.

booltrue
ShowSearch

Gets or sets whether the property search editor is shown.

booltrue
ShowToolbar

Gets or sets whether the property grid toolbar is shown.

booltrue
ShowViewModeButtons

Gets or sets whether the categorized and alphabetical view buttons are shown.

booltrue
TextEditorTemplate

Defines a text editor template.

RenderFragment<PropertyGridEditorContext>null
ToolbarAriaLabel

Gets or sets the accessible property grid toolbar label.

string"Property grid controls"
ToolbarTemplate

Defines the complete toolbar template.

RenderFragment<PropertyGridToolbarContext>null
ViewMode

Gets or sets how properties are arranged.

Possible values:Categorized, Alphabetical

PropertyGridViewModePropertyGridViewMode.Categorized

Events

PropertyGridView

Event Description Type
ActionInvoked

Occurs after a property action is invoked.

EventCallback<PropertyGridActionEventArgs>
GroupExpandedChanged

Occurs after a property group expansion state changes.

EventCallback<PropertyGridGroupExpandedEventArgs>
PropertyValueChanged

Occurs after a property value changes.

EventCallback<PropertyGridValueChangedEventArgs>
SearchTextChanged

Occurs after the property search text changes.

EventCallback<string>
SelectedPropertyChanged

Occurs after the selected property changes.

EventCallback<PropertyGridProperty>
ViewModeChanged

Occurs after the property arrangement changes.

EventCallback<PropertyGridViewMode>
On this page