UI Toolbox logoUI Toolbox

PropertyGrid

PropertyGrid in UIToolbox shows the public fields and properties of Target and edits them. Each row is an editor for the member type. A search box filters the rows. The "A-Z" button changes between category foldouts and one alphabetical list. The panel at the bottom shows the description of the selected row.

<tb:PropertyGrid name="grid" sort-mode="Categorized" show-search="true" show-description="true" />
class Settings
{
    [Category("Text"), Description("The text in the box.")] public string caption = "Hello";
    [Category("Size"), Range(40, 200)] public int width = 120;
    public Color fill = Color.blue;
    public int Edits { get; internal set; }        // no public setter: read-only row
    [DisplayName("Health")] public int MaxHealth { get; set; }
    [Choices(nameof(sizes))] public string Size = "M";        // a dropdown of the texts of sizes()
    public bool Outline;
    [EnabledIf(nameof(Outline))] public float OutlineWidth = 1;
    private string[] sizes() => new[] { "S", "M", "L" };
}

grid.Target = new Settings();
grid.PropertyValueChanged += (item, old, now) => Debug.Log($"{item.Name}: {old} > {now}");
grid.RegisterEditor(typeof(Color), item => myColorPicker(item)); // call item.SetValue(v) to write
Attribute Effect
[Category] The foldout of the row. The default is "Misc".
[Description], [Tooltip] The row tooltip and the description panel text.
[DisplayName] (properties only), [InspectorName] The row label. Otherwise the member name, nicified: maxHealth is "Max Health". C# does not allow [DisplayName] on a field; use [InspectorName] there.
[Choices(member)] A dropdown for a string or an int. member is a field, a property or a method without parameters of the same object, of any access, that returns a collection. A string takes the chosen text, an int takes its index. The grid reads the list again after each change.
[EnabledIf(member, values)] The row is enabled only while member is true, or equals one of values. The grid checks again after each change.
[Range] A slider for int, float, double, short, ushort, byte, sbyte, long, uint and ulong.
[Multiline], [TextArea] A multiline text field for string.
[ReadOnly(true)] A disabled row. readonly fields and properties without a public setter are disabled too.
[Browsable(false)], [HideInInspector], [Obsolete] The member has no row.
Type Editor
int, float IntegerField, FloatField, or SliderInt, Slider with [Range]
long, double, string LongField, DoubleField, TextField (delayed: the value changes on Enter or blur). A double with [Range] gets a Slider; a long with [Range] gets a SliderInt, or a long slider past the int limits.
uint, ulong UnsignedIntegerField, UnsignedLongField, or SliderInt with [Range], or a long slider past the int limits.
short, ushort, byte, sbyte IntegerField, or SliderInt with [Range]. The value is clamped to the type limits.
bool Toggle
enum EnumField; a [Flags] enum gets one toggle per flag
Vector2 to Vector4, Vector2Int, Vector3Int, Rect, RectInt, Bounds, BoundsInt The matching UI Toolkit field
Color A compact ColorPicker: a swatch in the row. A click on the swatch opens the full picker in a popup.
DateTime, TimeSpan DatePicker, TimeSpanPicker
A class or struct of your own A foldout with a row for each member. A null object shows "null" until code sets it and calls Refresh().
Other types A read-only text field with ToString(). A collection shows its type and count, such as "List (3)".
Member Description
Target The object to edit. A set builds the rows and clears the undo history.
SortMode (sort-mode) Categorized or Alphabetical.
DeclaredCategoryOrder (declared-category-order) True: the categories show in the order of their first member in the code. False (the default): A to Z.
ShowSearch, ShowDescription (show-search, show-description) The toolbar and the description panel.
SearchText The search text. It matches the label and the member name.
ShowClearButton (show-clear-button) On (the default): the search box shows a "x" button while it has text, and a click clears the text. Escape in the search box also clears the text. See Clear button.
Items, GetItem(path), GetEditor(path), SelectedItem The rows. A path is a member name or a dot path to a nested member, such as "stats.health". An element path has an index, such as "stops[2]" or "legs[0].health". PropertyGridItem has Name, Path, Parent, Children, DisplayName, Category, Description, ValueType, IsReadOnly, Range, Index (-1 for a member), GetValue() and SetValue(v).
InsertElement(index, value), RemoveElement(index) On the item of an array or list: insert or remove an element. value null gives a new element of the element type.
MoveElement(from, to) On the item of an array or list: move an element to another index; the other elements shift. One move is one undo step. It returns false for the same index, an index outside the collection, or a read-only list. A read-only array member reorders in place. Each element row has a "▲" and a "▼" button; the first row cannot move up and the last row cannot move down.
RegisterEditor(type, factory) Replaces the editor for a type and the types assignable to it. The first registered match wins.
Refresh() Reads the values again, for changes made outside the grid.
Undo(), Redo(), CanUndo, CanRedo The history. Ctrl+Z undoes; Ctrl+Y and Ctrl+Shift+Z redo.
PropertyValueChanged(item, old, new) Sent after an edit, an undo and a redo.

Styling

Class Element
tb-property-grid The grid (a border; it grows).
tb-property-grid__toolbar The row with the search box and the sort button.
tb-property-grid__search The search box.
tb-property-grid__sort, tb-property-grid__sort--active The "A-Z" button, and the button in alphabetical sort (accent).
tb-property-grid__body The scroll view with the rows.
tb-property-grid__category A category foldout (bold header on the alternate surface).
tb-property-grid__row A row: the editor field. The label is 40 % of the row.
tb-property-grid__row--selected The selected row (hover surface, accent left border).
tb-property-grid__long-input The exact number field in a long slider (110 px, no shrink).
tb-property-grid__nested The foldout of a nested object. Its content is indented by the medium spacing.
tb-property-grid__collection The foldout of an array or list. It has tb-property-grid__nested too.
tb-property-grid__element A line with an element row and its remove button.
tb-property-grid__move-up, tb-property-grid__move-down The "▲" and "▼" buttons of an element (20 x 18 px). They are disabled at the ends of the collection.
tb-property-grid__remove The "-" button of an element (20 x 18 px).
tb-property-grid__add The "+ Add" button under the elements.
tb-property-grid__flags The toggles of a [Flags] enum (a wrapped row).
tb-property-grid__empty The "No object" and "No properties" text (muted).
tb-property-grid__description, __description-title, __description-text The description panel (48 px high at least), its bold title and its muted text.