gum-tool-variable-grid
Reference guide for Gum's Variables tab and DataUiGrid system. Load this when working on the Variables tab, DataUiGrid control, MemberCategory, InstanceMember, category population, property grid refresh, or category expansion state persistence.
Best use case
gum-tool-variable-grid is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Reference guide for Gum's Variables tab and DataUiGrid system. Load this when working on the Variables tab, DataUiGrid control, MemberCategory, InstanceMember, category population, property grid refresh, or category expansion state persistence.
Teams using gum-tool-variable-grid should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/gum-tool-variable-grid/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How gum-tool-variable-grid Compares
| Feature / Agent | gum-tool-variable-grid | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Reference guide for Gum's Variables tab and DataUiGrid system. Load this when working on the Variables tab, DataUiGrid control, MemberCategory, InstanceMember, category population, property grid refresh, or category expansion state persistence.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Gum Variables Tab & DataUiGrid Reference
## Overview
The **Variables tab** displays and edits properties of the selected element, instance, state, or behavior. Built on `DataUiGrid` (a WPF `ItemsControl` subclass) from the `WpfDataUi` library. Categories render as collapsible `Expander` sections.
---
## Architecture Layers
```
[User selects object]
↓
[MainVariableGridPlugin] (event subscription)
↓
[PropertyGridManager.RefreshDataGrid()]
↓
[ElementSaveDisplayer.GetCategories()]
↓ (produces List<MemberCategory>)
[DataUiGrid.SetCategories()]
↓
[WPF Expander per MemberCategory, rows per InstanceMember]
```
---
## Key Files
| Purpose | File Path |
|---------|-----------|
| DataUiGrid control | `WpfDataUi/DataUiGrid.cs` |
| DataUiGrid XAML template | `WpfDataUi/Themes/Generic.xaml` |
| MemberCategory / InstanceMember models | `WpfDataUi/DataTypes/` |
| Gum-specific member subclass | `Gum/Plugins/InternalPlugins/VariableGrid/StateReferencingInstanceMember.cs` |
| Plugin wiring selection events | `Gum/Plugins/InternalPlugins/VariableGrid/MainVariableGridPlugin.cs` |
| Category population manager | `Gum/Plugins/InternalPlugins/VariableGrid/PropertyGridManager.cs` |
| Category factory | `Gum/Plugins/InternalPlugins/VariableGrid/ElementSaveDisplayer.cs` |
| Behavior categories | `Gum/Plugins/InternalPlugins/VariableGrid/BehaviorShowingLogic.cs` |
| Host UserControl | `Gum/Plugins/InternalPlugins/VariableGrid/MainPropertyGrid.xaml(.cs)` |
---
## Non-Obvious Behaviors
### SetCategories Expansion Preservation
`DataUiGrid.SetCategories()` captures `{name → IsExpanded}` from existing categories, replaces the list, then re-applies the saved values by name. Category collapse state persists across selection changes within a session. `IsExpanded` is `Mode=TwoWay` in the XAML template so user gestures write back to the model immediately.
### Structural Rebuild vs. Partial Refresh
`PropertyGridManager.RefreshDataGrid` tracks the previous display target (element, state, instances, behavior). If unchanged and `force=false`, it calls `Refresh()` to update values without recreating categories. If the target changed, it calls `SetCategories` with a fresh list from `ElementSaveDisplayer`. Pass `force: true` to always rebuild.
### Control Recycling (SingleDataUiContainer)
`SingleDataUiContainer` maintains a static `Dictionary<Type, Stack<UserControl>>` pool. When a container is removed from the visual tree (`Unloaded`), its inner displayer control is detached and pushed onto the type-keyed stack. When a new container needs a displayer, `CreateInternalControl` first checks if the existing control already matches the needed type (reuse in-place — preserves focus), then tries the pool via `TryGetFromPool`, and only falls back to `Activator.CreateInstance` if both miss. Pooled controls must clean up stale state when reassigned to a new `InstanceMember` (e.g., `TextBoxDisplay` detaches old event handlers, resets error/multiline state, and calls `Refresh`). `SetCategories` uses `BulkObservableCollection.ReplaceAll` (single `Reset` notification) which triggers WPF to unload old containers (returning controls to the pool) and create new ones (pulling from the pool).
### Multi-Select Path
When multiple instances are selected, `SetMultipleCategoryLists` is used instead of `SetCategories`. `MultiSelectInstanceMember` wrappers coordinate synchronized edits across all selected instances and record a single undo after all values are set.
### StateReferencingInstanceMember
All members in the Variables tab use `StateReferencingInstanceMember` (subclass of `InstanceMember`), not the generic reflection path. Its `IsReadOnly` returns `true` when `InstanceSave?.Locked == true`. Its `IsDefault` returns `true` when the value is absent from the selected state (not inherited from defaults).
---
## Refresh Trigger Flow
```
Selection changed
→ MainVariableGridPlugin.Handle*Selected()
→ PropertyGridManager.RefreshEntireGrid(force: true)
→ RefreshDataGrid(...)
├─ Target changed?
│ yes → ElementSaveDisplayer.GetCategories()
│ → DataUiGrid.SetCategories() ← preserves IsExpanded by name
└─ Target same?
→ DataUiGrid.Refresh() ← only updates member values
```
### Double-Refresh Guard (Instance Selection)
When an instance is selected, two events fire in sequence: the default state is force-selected first (via `PerformAfterSelectInstanceLogic`), then the instance-selected event fires. Without a guard, the grid rebuilds twice.
```
Selection changed (instance)
→ HandleStateSelected() (state force-selected first)
→ RefreshEntireGrid(force: true) + sets _stateJustRefreshedGrid
→ HandleInstanceSelected() (fires second)
→ _stateJustRefreshedGrid is true → skip redundant refresh
```
`_stateJustRefreshedGrid` is cleared by `HandleElementSelected` and `HandleTreeNodeSelected` so it does not suppress legitimate refreshes during unrelated selections.
Variable set by UI:
```
InstanceMember.AfterSetByUi
→ StateReferencingInstanceMember.NotifyVariableLogic()
→ PropertyGridManager.RefreshEntireGrid(force: false)
→ DataUiGrid.Refresh() (no structural rebuild needed)
```
---
## Common Patterns
### Making a category collapsed by default
Set `IsExpanded = false` on the `MemberCategory` before passing to `SetCategories`. The first time the category appears it uses the incoming value; subsequent appearances restore the user's last state.
### Forcing a full grid rebuild
Call `PropertyGridManager.RefreshEntireGrid(force: true)`. The `force` flag bypasses the same-target optimization and always recreates categories.Related Skills
gum-variable-deep-dive
Deep dive into the full variable lifecycle — from VariableSave on ElementSave through runtime application on GraphicalUiElement and Forms controls. Load this when working on styling, theming, RefreshStyles, or when you need to understand how variable values flow from save data to live visuals.
gum-tool-viewmodels
Reference guide for Gum tool ViewModel conventions. Load this when working on ViewModels, XAML views, data binding, DependsOn, or visibility properties in the Gum tool.
gum-tool-variable-references
Reference guide for Gum's variable reference system — Excel-like cross-instance/cross-element variable binding using Roslyn-parsed assignment syntax. Load this when working on VariableReferenceLogic, EvaluatedSyntax, ApplyVariableReferences, VariableChangedThroughReference, or the VariableReferences VariableListSave.
gum-tool-undo
Reference guide for Gum's undo/redo system. Load this when working on undo/redo behavior, the History tab, UndoManager, UndoPlugin, UndoSnapshot, or stale reference issues after undo.
gum-tool-selection
Reference guide for Gum's editor selection system. Load this when working on click/drag selection, the rectangle/marquee selector, input handlers (move, resize, rotate, polygon points), the IsActive flag, locked instance behavior, SelectionManager coordination, or the selection event cascade (plugin events, forced default state, tree view sync).
gum-tool-save-classes
Reference guide for Gum's save/load data model. Load this when working with GumProjectSave, ScreenSave, ComponentSave, StandardElementSave, ElementSave, StateSave, VariableSave, InstanceSave, BehaviorSave, or any serialization/deserialization of Gum project files.
gum-tool-plugins
Reference guide for the Gum tool's plugin system, including visualization plugins (EditorTabPlugin_XNA, TextureCoordinateSelectionPlugin). Load this when working on plugin registration, PluginBase, InternalPlugin, PluginManager, plugin events, visualization/rendering concerns, or finding which internal plugin owns a feature.
gum-tool-output
Reference guide for Gum's Output tab system. Load this when working on the Output tab, IOutputManager, MainOutputViewModel, GuiCommands.PrintOutput, or adding output/error messages to the tool.
gum-tool-font-generation
Reference guide for Gum's bitmap font generation pipeline — how the tool converts font properties into .fnt/.png files via bmfont.exe. Load this when working on BmfcSave, HeadlessFontGenerationService, FontManager, BmfcTemplate.bmfc, font cache naming, texture size estimation, or the GumProjectFontGenerator CLI.
gum-tool-file-watch
Reference guide for Gum's FileWatch system. Load this when working on file watching, external file change detection, IgnoreNextChangeUntil, FileWatchManager, FileWatchLogic, FileChangeReactionLogic, or reloading assets/elements when files change on disk.
gum-tool-errors
Reference guide for Gum's error detection and display system. Load this when working on the Errors tab, error icons ("!" mark) in the tree view, ErrorChecker, ErrorViewModel, IErrorChecker, AllErrorsViewModel, MainErrorsPlugin, RequestErrorRefreshMessage, or adding new error checks.
gum-tool-dialogs
Reference guide for Gum's dialog/popup systems. Load this when working on dialog windows, DialogService, DialogWindow, DeleteOptionsWindow, dialog scrolling, dialog layout, or adding new dialog types.