BeepCheckBox
Generic checkbox control with multi-style painter system, three-state support, and data-binding to typed values
Table of Contents
Overview
Namespace: TheTechIdea.Beep.Winform.Controls.CheckBoxes
Assembly: TheTechIdea.Beep.Winform.Controls
Inheritance: BeepCheckBox<T> → BaseControl → System.Windows.Forms.UserControl
Implements: IBeepComponent
BeepCheckBox<T> is a generic, themable checkbox control that supports a pluggable painter system
for rendering styles (Material3, Fluent2, iOS, Classic, and more). It provides three-state checking
(Unchecked / Checked / Indeterminate), typed value mapping, keyboard and mouse interaction, DPI
scaling, grid-mode rendering, and full data-binding through the IBeepComponent interface.
The control is implemented as a generic BeepCheckBox<T> partial class split across six files.
Three concrete non-generic wrappers are provided for design-time toolbox use. The painter system
delegates all visual rendering to ICheckBoxPainter implementations selected by the
CheckBoxStyle enum, allowing the same control to render as a classic checkbox, a Material3
checkmark, an iOS-style animated toggle, or a Windows Fluent2 checkbox.
State and value management is handled through a layered system: legacy CheckedValue /
UncheckedValue properties coexist with explicit CheckedStateValue /
UncheckedStateValue / IndeterminateStateValue properties, with automatic
synchronisation controlled by MapStateValuesToLegacy. The CurrentValue
property always resolves to the correct typed value for the current CheckBoxState.
Key Features
- Pluggable Painter System: Rendering delegated to
ICheckBoxPainterimplementations (Classic, Fluent2, iOS, Material3, Minimal, Modern, Switch, Button) viaCheckBoxPainterFactory. - Generic Value Mapping:
BeepCheckBox<T>maps checked/unchecked/ indeterminate states to any typed value (bool, string, int, char, custom enums). - Three-State Support: Cycles Unchecked → Checked → Indeterminate with full value resolution per state. ToggleState() handles the cycling logic.
- Eight Visual Styles: Classic, Fluent2, iOS, Material3, Minimal, Modern, Switch, Button — each with its own painter and layout recommendations.
- State-Aware Value Resolution: Explicit
CheckedStateValue,UncheckedStateValue,IndeterminateStateValuewith backward-compatibleMapStateValuesToLegacybridging. - Grid-Mode Optimisation: When
GridMode=true,DrawForGridprovides a simplified, cache-friendly rendering path without painter or rounded-corner overhead. - DPI Scaling: All layout dimensions (checkbox size, spacing, border radius,
check-mark thickness) scaled through
DpiScalingHelper. - Hit-Mode Control:
CheckBoxMouseHitMode— WholeControl or CheckBoxGlyph — determines where clicks trigger toggling. - Keyboard & Accessibility: Space/Enter toggle, arrow-key navigation,
mnemonics, and custom
BeepCheckBoxAccessibleObjectfor UIA/screen readers. - Diagnostics:
BeepCheckBoxDiagnosticswith DEBUG-only counters for invalidation, toggle, cache-rebuild, and painter-fetch regression testing. - IBeepComponent Integration:
SetValue,GetValue,ClearValue,HasFilterValue,ToFilter,BoundProperty. - Image Support: Custom check-mark via
ImagePath(SVG, PNG, JPG) with theme-aware SVG recolouring throughBeepImage. - Auto-Sync:
SyncLayoutMetricsWithStyleandSyncControlStyleWithCheckBoxStyleauto-apply recommendations when style changes.
Concrete (Non-Generic) Types
| Type | CheckedValue | UncheckedValue | Default CurrentValue |
|---|---|---|---|
BeepCheckBoxBool | true | false | false |
BeepCheckBoxChar | 'Y' | 'N' | 'N' |
BeepCheckBoxString | "YES" | "NO" | "NO" |
All three are decorated with [ToolboxItem(true)], [Category("Beep Controls")],
and descriptive [DisplayName] / [Description] attributes for Visual Studio toolbox integration.
For custom typed values (e.g. enums, integers), instantiate BeepCheckBox<T> directly
and configure CheckedStateValue / UncheckedStateValue as needed.
Properties (35 total)
| Property | Type | Default | Category | Description |
|---|---|---|---|---|
TextFont | Font | SystemFonts.MessageBoxFont | Appearance | Font used for the checkbox label text. Setting disables UseThemeFont. |
Text (override) | string | "" | Appearance | Label text displayed adjacent to the glyph. Triggers AutoSize recalc and visual refresh. |
TextAlignRelativeToCheckBox | TextAlignment | Right | Appearance | Position of the label relative to the glyph: Right, Left, Above, Below. |
CheckMark | CheckMarkShape | Square | Appearance | Shape of the check-mark glyph (Square, Circular, etc.). Hidden from design ser. |
CheckBoxStyle | CheckBoxStyle | Material3 | Appearance | Visual style: Classic, Fluent2, iOS, Material3, Minimal, Modern, Switch, Button. |
ControlStyle (new) | BeepControlStyle | (style-derived) | Appearance | BaseControl visual style. Manual sets disable auto-sync. |
SyncLayoutMetricsWithStyle | bool | true | Layout | Auto-apply CheckBoxSize, Spacing, HitTargetSize when CheckBoxStyle changes. |
SyncControlStyleWithCheckBoxStyle | bool | true | Appearance | Auto-sync BaseControl.ControlStyle to CheckBoxStyle mapping. |
State | CheckBoxState | Unchecked | Appearance | Current state (Unchecked/Checked/Indeterminate). Full SetStateCore pipeline. |
Checked | bool | false | Behavior | Convenience: true=Checked, false=Unchecked. Sets State accordingly. |
CheckState | CheckBoxState | Unchecked | Behavior | Alias for State — full three-state get/set. |
ThreeState | bool | true | Behavior | Enable Unchecked→Checked→Indeterminate cycle. When false, Indeterminate resets to Unchecked. |
AutoCheck | bool | true | Behavior | Allow keyboard/mouse interaction to auto-toggle state. |
MouseHitMode | CheckBoxMouseHitMode | WholeControl | Behavior | Toggle from anywhere (WholeControl) or only glyph (CheckBoxGlyph). |
ReadOnly | bool | false | Behavior | Prevent user state changes while keeping the control enabled. |
CheckedValue | T | (type default) | Behavior | Legacy value for Checked state. Synced from CheckedStateValue when MapStateValuesToLegacy=true. |
UncheckedValue | T | (type default) | Behavior | Legacy value for Unchecked state. Synced from UncheckedStateValue when MapStateValuesToLegacy=true. |
CheckedStateValue | T | (type default) | Behavior | Explicit value for Checked. Flags _hasCheckedStateValue and optionally syncs to CheckedValue. |
UncheckedStateValue | T | (type default) | Behavior | Explicit value for Unchecked. Flags _hasUncheckedStateValue and optionally syncs to UncheckedValue. |
IndeterminateStateValue | T | (type default) | Behavior | Explicit value for Indeterminate. Flags _hasIndeterminateStateValue. |
MapStateValuesToLegacy | bool | true | Behavior | Sync CheckedStateValue/UncheckedStateValue to CheckedValue/UncheckedValue for backward compat. |
UseUncheckedValueForIndeterminate | bool | true | Behavior | When IndeterminateStateValue not set, map indeterminate to UncheckedValue (true) or CheckedValue (false). |
CurrentValue | T | (state-resolved) | Behavior | Current resolved value based on state. Setting resolves and changes state. |
HideText | bool | false | Appearance | When true, label text is not painted. Affects GetPreferredSize. |
ImagePath | string | "" | Appearance | Path to custom check-mark image (SVG/PNG/JPG). FileNameEditor at design time. |
CheckIconPath | string | (IconsMgmt default) | Appearance | Icon path for checked glyph. Falls back to IconsManagement defaults when empty. |
IndeterminateIconPath | string | (IconsMgmt default) | Appearance | Icon path for indeterminate glyph. Falls back to IconsManagement defaults when empty. |
MinimumHitTargetSize | int | 32 | Layout | Minimum clickable target size. Clamped ≥24. Affects GetPreferredSize. |
MinimumAutoSizeWidth | int | 0 | Layout | Width floor for AutoSize. 0 disables. Affects GetPreferredSize. |
CheckBoxSize | int | 15 | Appearance | Glyph size in logical pixels. Clamped ≥12. Affects AutoSize. |
Spacing | int | 5 | Layout | Gap between glyph and label. Clamped ≥2. Affects AutoSize. |
TabStop (new) | bool | true | Behavior | Whether the control receives focus via Tab navigation. |
AutoSize (override) | bool | false | Layout | Auto-resize to preferred dimensions (glyph+text+padding). |
BoundProperty | string | "CurrentValue" | Data | Property name for data-binding resolution (IBeepComponent). |
IsReadOnly | bool | false | Behavior | Internal read-only flag. Exposed via ReadOnly property and used in SetStateCore / accessibility. |
Methods
| Method | Visibility | Signature | Description |
|---|---|---|---|
ApplyTheme | public | void ApplyTheme() | Applies current theme to fonts, colours, BeepImage. Rebuilds text font via CheckBoxFontHelpers, clears caches, requests refresh. |
SetValue | public | void SetValue(object value) | Sets CurrentValue. Supports typed T assignment, bool-to-string coercion, byte/int-to-bool coercion, Convert.ChangeType. IBeepComponent. |
GetValue | public | object GetValue() | Returns CurrentValue as object. IBeepComponent. |
ClearValue | public | void ClearValue() | Resets CurrentValue to default(T). IBeepComponent. |
HasFilterValue | public | bool HasFilterValue() | Returns true when any bound value (Checked/CheckState/State/CurrentValue) is non-null. |
ToFilter | public | AppFilter ToFilter() | Creates equality AppFilter (FieldName=BoundProperty, Operator="="). |
GetPreferredSize | public | Size GetPreferredSize(Size) | Computes optimal size: glyph+spacing+text+padding+hit-target. Handles all TextAlignment directions. |
Draw | public | void Draw(Graphics, Rectangle) | Main paint: layout via CheckBoxLayoutCalculator, glyph via ICheckBoxPainter, text via painter.PaintText. GridMode uses DrawForGrid. |
DrawContent | protected | void DrawContent(Graphics) | Called by BaseControl on WM_PAINT. Delegates to Paint(g, DrawingRect). |
CreateAccessibilityInstance | protected | AccessibleObject CreateAccessibilityInstance() | Returns BeepCheckBoxAccessibleObject with dynamic Name, Description, DefaultAction, Role=CheckButton. |
SetStateCore | private | void SetStateCore(state, syncValue, raiseEvents, raiseSubmit) | Central state mutation. No-op when unchanged (+ optional value sync). Raises CheckStateChanged/CheckedChanged/StateChanged. |
ToggleState | private | void ToggleState() | Cycles: Unchecked→Checked→Indeterminate→Unchecked. TwoState: binary toggle. Records diagnostic toggle. |
ClearGraphicsCaches | private | void ClearGraphicsCaches() | Disposes & clears _brushCache, _penCache, _pathCache. Records diagnostic CacheRebuild. Called on theme/DPI/font change and Dispose. |
RequestVisualRefresh | private | void RequestVisualRefresh(bool includeText) | Sets _stateChanged=true, records diagnostic invalidation, calls Invalidate(GetDirtyRegion). |
ResolveBoundValue | private | object ResolveBoundValue() | Returns the value for BoundProperty: Checked (bool), CheckState (enum), State (enum), or CurrentValue (T). |
ResolveStateFromCurrentValue | private | CheckBoxState ResolveStateFromCurrentValue(T) | Matches currentValue against Checked/Unchecked/Indeterminate values, with bool special case. |
UpdateCurrentValue | private | void UpdateCurrentValue() | Sets _currentValue = ResolveValueForState(_state), raises StateChanged, requests refresh. |
ProcessMnemonic | protected | bool ProcessMnemonic(char) | When focused and mnemonic matches Text, toggles state if enabled and !ReadOnly. |
Events
| Event | Args Type | Fire Condition | Description |
|---|---|---|---|
CheckStateChanged | EventHandler | State changes to a different CheckBoxState | Raised on any state transition (Unchecked/Checked/Indeterminate). Fired before CheckedChanged. |
CheckedChanged | EventHandler | CheckState transitions between Checked and non-Checked | Only fired when the boolean Checked value changes. Not fired on Checked→Indeterminate or Indeterminate→Checked round-trips. |
StateChanged | EventHandler | Any state or CurrentValue change | General change notification. Fires on UpdateCurrentValue and all SetStateCore invocations. |
All three events are invoked through OnStateChanged(previousState, checkedChanged, raiseSubmitChanges),
which also calls AccessibilityNotifyClients for UIA state/name change notifications,
and optionally RaiseSubmitChanges() for the form-level submit pipeline.
Theming
BeepCheckBox supports two parallel theming axes:
- CheckBoxStyle — selects the
ICheckBoxPainterand applies style-specific layout recommendations viaCheckBoxStyleHelpers:Classic— Windows classic appearance with square glyph and etched borderFluent2— Microsoft Fluent 2 design language with rounded animated filliOS— iOS-style with animated scale/opacity on checkMaterial3— Material Design 3 checkmark with ink ripple (default)Minimal— Minimalist line-art with no fillModern— Rounded-square with gradient fillSwitch— Toggle-switch appearance with sliding thumbButton— Push-button style with raised/lowered states
- BeepControlStyle (via
ControlStyle) — controls BaseControl-level rendering (borders, background, shadows). WhenSyncControlStyleWithCheckBoxStyleis true, mapped automatically viaCheckBoxStyleHelpers.GetControlStyleForCheckBox().
The CheckBoxRenderOptions struct carries theme-derived values to the painter:
Theme, UseThemeColors, ControlStyle, CheckBoxStyle, CheckBoxSize, Spacing, Padding, BorderRadius,
BorderWidth, CheckMarkThickness, GlyphSizeRatio, CheckIconPath, IndeterminateIconPath, TextFont,
Text, HideText, TextAlignment, RightToLeft.
Layout geometry is computed by CheckBoxLayoutCalculator.Compute() and
CheckBoxLayoutCalculator.ComputeGrid(). Theme colours are resolved by
CheckBoxThemeHelpers for background (checked/unchecked), foreground, border,
check-mark, and indeterminate fill. Fonts are resolved by CheckBoxFontHelpers.GetCheckBoxFont().
Icons default via CheckBoxIconHelpers.GetCheckIconPath() and
GetIndeterminateIconPath().
Examples
Basic Usage — BeepCheckBoxBool
var checkBox = new BeepCheckBoxBool
{
Text = "Enable feature",
Checked = true,
TextAlignRelativeToCheckBox = TextAlignment.Right,
CheckBoxStyle = CheckBoxStyle.Material3,
AutoSize = true
};
checkBox.CheckedChanged += (s, e) =>
Console.WriteLine($"Checked: {checkBox.Checked}");
Three-State Toggle
var triCheck = new BeepCheckBoxBool
{
Text = "Include all sub-items",
ThreeState = true,
CheckBoxStyle = CheckBoxStyle.iOS
};
triCheck.State = CheckBoxState.Indeterminate;
Generic with Custom Typed Values
var statusCheck = new BeepCheckBox<string>
{
Text = "Approval Status",
CheckedStateValue = "APPROVED",
UncheckedStateValue = "REJECTED",
IndeterminateStateValue = "PENDING",
MapStateValuesToLegacy = true
};
Console.WriteLine(statusCheck.CurrentValue); // "REJECTED"
statusCheck.State = CheckBoxState.Checked;
Console.WriteLine(statusCheck.CurrentValue); // "APPROVED"
Data Binding via IBeepComponent
var checkBox = new BeepCheckBoxBool { BoundProperty = "CurrentValue" };
checkBox.SetValue(true); // sets Checked = true
object val = checkBox.GetValue(); // returns true
var filter = checkBox.ToFilter(); // FieldName="CurrentValue", FilterValue="True", Operator="="
Hit-Mode: Glyph-Only Toggling
var checkBox = new BeepCheckBoxBool
{
Text = "Click the box only — label won't toggle",
MouseHitMode = CheckBoxMouseHitMode.CheckBoxGlyph
};
Custom Image as Check Mark
var imgCheck = new BeepCheckBoxBool
{
Text = "Favourite",
ImagePath = @"C:\icons\star.svg",
CheckBoxStyle = CheckBoxStyle.Modern
};
// SVG is loaded, theme-coloured, and rendered as the checked glyph
Grid-Mode Rendering (for BeepGridPro cells)
// BeepGridPro sets GridMode=true for hosted cells automatically
// No user code needed — DrawForGrid handles simplified rendering
// Key: flat glyph, no rounded corners, no shadows, cached brush/pen reuse
BeepCheckBoxString for Data-Backed Forms
var ynCheck = new BeepCheckBoxString
{
Text = "Export to CSV",
BoundProperty = "CurrentValue"
};
ynCheck.SetValue("YES"); // Checked = true
ynCheck.SetValue("NO"); // Checked = false
Architecture
| File | Lines | Responsibility |
|---|---|---|
BeepCheckBox.cs | ~831 | Main class: generic BeepCheckBox<T> + Bool/Char/String wrappers. All properties (35), constructor, ApplyTheme, accessibility (BeepCheckBoxAccessibleObject), event declarations. |
BeepCheckBox.IBeepComponent.cs | ~89 | IBeepComponent: SetValue (with type coercion), GetValue, ClearValue, HasFilterValue, ToFilter, BoundProperty, ResolveBoundValue. |
BeepCheckBox.Drawing.cs | ~342 | Rendering: Draw (painter-based), DrawForGrid (grid-mode simplified), GetPreferredSize, Paint, DrawThemedCheckMark, DrawThemedIndeterminateMark, CheckIfStateChanged, DrawAlignedText. |
BeepCheckBox.Methods.cs | ~274 | State management: SetStateCore, ToggleState, UpdateCurrentValue, SetCurrentValueCore, ResolveStateFromCurrentValue, OnStateChanged, ClearGraphicsCaches, Dispose, RequestVisualRefresh, GetDirtyRegion. |
BeepCheckBox.Events.cs | ~158 | Input: OnTextChanged, OnKeyDown (Space/Enter/Tab/Arrows), OnGotFocus, OnLostFocus, OnMouseClick (hit-mode check), OnMouseMove (cursor), OnMouseLeave, OnMouseDown, OnMouseUp, ProcessMnemonic, OnHandleDestroyed, IsInputKey. |
BeepCheckBoxDiagnostics.cs | ~77 | Diagnostics: InvalidationCount, ToggleCount, CacheRebuildCount, PainterFetchCount, Reset. All counters are Interlocked.Increment in DEBUG, no-op in Release. |
Painters/ICheckBoxPainter.cs | ~20 | Interface: PaintCheckBox(Graphics, Rectangle, CheckBoxItemState, CheckBoxRenderOptions), PaintText(Graphics, Rectangle, string, CheckBoxRenderOptions). |
Painters/CheckBoxPainterFactory.cs | ~40 | Factory: static GetPainter(CheckBoxStyle) returns ICheckBoxPainter. Records diagnostics. |
Painters/CheckBoxPainterBase.cs | ~60 | Abstract base with shared helper methods (DrawCheckMark, DrawIndeterminateMark, etc.). |
Painters/ClassicCheckBoxPainter.cs | ~80 | Classic Windows style: etched border, flat fill, simple check mark. |
Painters/Fluent2CheckBoxPainter.cs | ~80 | Fluent 2: rounded corners, animated background fill, smooth check mark animation. |
Painters/iOSCheckBoxPainter.cs | ~80 | iOS style: scale/opacity animation on check, circular fill. |
Painters/Material3CheckBoxPainter.cs | ~80 | Material3: ink ripple, colour transitions, squared check mark. |
Painters/MinimalCheckBoxPainter.cs | ~80 | Minimal: line-only check, no fill, clean aesthetic. |
Painters/ModernCheckBoxPainter.cs | ~80 | Modern: rounded-square with gradient fill, bold check mark. |
Painters/SwitchCheckBoxPainter.cs | ~80 | Switch: toggle-switch with sliding thumb. |
Painters/ButtonCheckBoxPainter.cs | ~80 | Button: push-button appearance with raised/lowered 3D effect. |
Helpers/CheckBoxLayoutCalculator.cs | ~80 | Static Compute() and ComputeGrid() methods. Calculates CheckBoxRect, TextRect from control size, text, alignment, RTL, DPI. |
Helpers/CheckBoxStyleHelpers.cs | ~60 | Style recommendations: GetRecommendedCheckBoxSize, GetRecommendedSpacing, GetRecommendedBorderRadius, GetRecommendedBorderWidth, GetRecommendedCheckMarkThickness, GetRecommendedMinimumHitTargetSize, GetControlStyleForCheckBox. |
Helpers/CheckBoxThemeHelpers.cs | ~60 | Theme colours: GetCheckedBackgroundColor, GetUncheckedBackgroundColor, GetForegroundColor, GetBorderColor, GetCheckMarkColor, GetIndeterminateMarkColor. |
Helpers/CheckBoxFontHelpers.cs | ~30 | Font resolution: GetCheckBoxFont(IBeepTheme, BeepControlStyle, Control) returns Font. |
Helpers/CheckBoxIconHelpers.cs | ~30 | Icon defaults: GetCheckIconPath(), GetIndeterminateIconPath(). |
Models/CheckBoxStyleConfig.cs | ~40 | Style configuration model: layout presets per CheckBoxStyle. |
Models/CheckBoxColorConfig.cs | ~40 | Colour configuration per CheckBoxStyle per CheckBoxState. |
Painter Details
Each ICheckBoxPainter implementation receives a CheckBoxItemState
(IsChecked, IsIndeterminate, IsHovered, IsPressed, IsFocused, IsDisabled) and a
CheckBoxRenderOptions (all theme-derived visual parameters). The painter's
PaintCheckBox method draws the glyph, and PaintText draws the label.
Painters are stateless — they hold no GDI resources and are allocated per CheckBoxStyle change.
The factory (CheckBoxPainterFactory.GetPainter) returns the cached painter instance
for the requested style, recording a diagnostic PainterFetch on each call.
Grid-Mode Rendering
When GridMode = true (set by BeepGridPro when hosting the checkbox in a cell),
the Draw method delegates to DrawForGrid which provides a deliberately
simplified rendering path:
- No painter system — flat rectangles, simple lines
- No rounded corners, shadows, or animations
- Brush and pen caching for repeated colour access
- DPI-scaled glyph size clamped to min(16, CheckBoxSize)
- EndEllipsis text with RTL support
- Colours resolved via CheckBoxThemeHelpers with disabled-state luminance shift
This keeps grid-cell overhead minimal when hundreds of cells may share the same control instance.