Show / Hide Table of Contents

KryptonPropertyGrid

Overview

The KryptonPropertyGrid class provides a Krypton-themed wrapper around the standard Windows PropertyGrid control. It inherits from VisualControlBase and implements IContainedInputControl to provide enhanced appearance, consistent theming, and improved visual integration while maintaining full compatibility with the standard PropertyGrid functionality.

Class Hierarchy

System.Object
└── System.MarshalByRefObject
    └── System.ComponentModel.Component
        └── System.Windows.Forms.Control
            └── Krypton.Toolkit.VisualControlBase
                └── Krypton.Toolkit.KryptonPropertyGrid

Constructor and Initialization

public KryptonPropertyGrid

The constructor initializes enhanced features:

  • Internal PropertyGrid: Creates and manages the contained PropertyGrid instance
  • Visual States: Sets up Common, Normal, Disabled, and Active palette states
  • Event Delegation: Proper event routing to the contained control
  • Context Menu: Integrated Krypton context menu with reset functionality
  • Palette Integration: Automatic theme detection and application

Key Properties

ContainedControl Property

[Browsable(false)]
public Control ContainedControl => _propertyGrid;
  • Purpose: Provides access to the underlying PropertyGrid for advanced customization
  • Category: Runtime only (hidden from designer)
  • Access Level: Protected but accessible for integration scenarios

PropertyGrid Property

[Browsable(false)]
public PropertyGrid PropertyGrid => _propertyGrid;
  • Purpose: Direct access to the wrapped PropertyGrid instance
  • Usage: For scenarios requiring access to native PropertyGrid features
  • Integration: Allows custom PropertyGrid-specific configuration

Visual State Properties

public PaletteInputControlTripleRedirect StateCommon { get; }
public PaletteInputControlTripleStates StateDisabled { get; }
public PaletteInputControlTripleStates StateNormal { get; }
public PaletteInputControlTripleStates StateActive { get; }
  • StateCommon: Base styling configuration for all states
  • StateNormal: Default appearance when enabled but not active
  • StateActive: Highlighted appearance when focused/active
  • StateDisabled: Appearance when control is disabled

AlwaysActive Property

[DefaultValue(false)]
public bool AlwaysActive { get; set; }
  • Purpose: Forces the control to always appear in active state
  • Category: Visuals
  • Use Case: When PropertyGrid should always look selected/focused

IsActive Property

[Browsable(false)]
public bool IsActive { get; }
  • Purpose: Read-only property indicating current active state
  • Logic: DesignMode || AlwaysActive || ContainsFocus

Standard PropertyGrid Properties

CommandsVisibleIfAvailable Property

[DefaultValue(true)]
public bool CommandsVisibleIfAvailable { get; set; }
  • Purpose: Shows commands pane for objects that expose verbs
  • Category: Appearance
  • Integration: Directly bound to contained PropertyGrid

HelpVisible Property

[DefaultValue(true)]
public bool HelpVisible { get; set; }
  • Purpose: Controls visibility of the help description pane
  • Category: Appearance
  • Localizable: Yes

CanShowVisualStyleGlyphs Property

[DefaultValue(true)]
public bool CanShowVisualStyleGlyphs { get; set; }
  • Purpose: Uses OS-specific visual style glyphs for expansion nodes
  • Category: Appearance
  • Effect: Modern glyphs vs. legacy symbols

PropertySort Property

[DefaultValue(PropertySort.CategorizedAlphabetical)]
public PropertySort PropertySort { get; set; }
  • Available Options:
    • Alphabetical: Alphabetical sorting only
    • Categorized: Category grouping only
    • CategorizedAlphabetical: Categories with alphabetical order (default)
    • NoSort: Display properties in declaration order

SelectedObject Property

[TypeConverter(typeof(SelectedObjectConverter))]
public object? SelectedObject { get; set; }
  • Purpose: Sets the primary object for property inspection
  • Category: Behavior
  • TypeConverter: Specialized converter for IComponent objects

Multi-Object Selection

[Browsable(false)]
public object[] SelectedObjects { get; set; }
  • Purpose: Supports inspection of multiple objects simultaneously
  • Category: Runtime only
  • Use Case: Comparing properties across multiple instances

Appearance Options

[DefaultValue(false)]
public bool LargeButtons { get; set; }

[DefaultValue(true)]
public bool ToolbarVisible { get; set; }
  • LargeButtons: Increases command button sizes for better accessibility
  • ToolbarVisible: Shows/hides the toolbar strip with commands

Advanced Features

Dark Mode Integration

The PropertyGrid automatically adapts to dark themes:

public void ConfigureDarkMode()
{
    var palette = KryptonManager.CurrentGlobalPalette;
    var colorTable = palette.ColorTable;
    
    // Automatically adjusts colors for dark themes
    propertyGrid.CategoryForeColor = palette.ToString().Contains("DarkMode")
        ? colorTable.MenuStripText
        : colorTable.ToolStripDropDownBackground;
}

Custom Context Menu

The control provides an enhanced context menu with reset functionality:

public partial class EnhancedPropertyGrid : KryptonPropertyGrid
{
    protected override void OnPropertyValueChanged(PropertyValueChangedEventArgs e)
    {
        base.OnPropertyValueChanged(e);
        
        // Log property changes for debugging
        Console.WriteLine($"Property '{e.ChangedItem.PropertyDescriptor.Name}' changed from '{e.OldValue}' to '{e.ChangedItem.Value}'");
    }
}

Theme-Aware Property Editing

public class ThemeAwarePropertyEditor : Form
{
    private KryptonPropertyGrid propertyGrid;

    public void EditComponent(IComponent component)
    {
        propertyGrid.SelectedObject = component;
        
        // Configure appearance based on component type
        ConfigureForComponentType(component.GetType());
    }

    private void ConfigureForComponentType(Type componentType)
    {
        // Example: Different configuration for different component types
        if (componentType.IsSubclassOf(typeof(Control)))
        {
            propertyGrid.ToolbarVisible = true;
            propertyGrid.LargeButtons = true;
        }
        else
        {
            propertyGrid.ToolbarVisible = false;
            propertyGrid.LargeButtons = false;
        }

        propertyGrid.PropertySort = PropertySort.CategorizedAlphabetical;
        propertyGrid.HelpVisible = true;
    }
}

Integration Patterns

Design-Time Property Editing

public class ComponentDesigner : Form
{
    private KryptonPropertyGrid propertyGrid;

    public void EditComponent(IComponent component)
    {
        propertyGrid.SelectedObject = component;
        
        // Enable design-time specific features
        propertyGrid.CommandsVisibleIfAvailable = true;
        propertyGrid.CanShowVisualStyleGlyphs = true;
        
        // Configure context for design-time
        SetupDesignTimeContext();
    }

    private void SetupDesignTimeContext()
    {
        // Show design-time specific commands
        propertyGrid.ToolbarVisible = true;
        
        // Enable help pane for designer guidance
        propertyGrid.HelpVisible = true;
    }
}

Runtime Configuration Editor

public class ConfigurationEditor : UserControl
{
    private KryptonPropertyGrid configGrid;

    public void EditSettings(SettingsBase settings)
    {
        configGrid.SelectedObject = settings;
        
        // Configure for runtime settings editing
        configGrid.ToolbarVisible = false; // Cleaner appearance
        configGrid.HelpVisible = false; // Reduce UI clutter
        
        // Sort settings logically
        configGrid.PropertySort = PropertySort.CategorizedAlphabetical;
    }

    public void EditMultipleSettings(SettingsBase[] settingsArray)
    {
        // Enable multi-object inspection for comparing settings
        configGrid.SelectedObjects = settingsArray;
        
        // Configure multi-object display
        configGrid.HelpVisible = true; // Show help for multi-object scenarios
    }
}

Dynamic Property Inspection

public class DynamicPropertyInspector : UserControl
{
    private KryptonPropertyGrid inspector;
    
    public void InspectObject(object targetObject)
    {
        inspector.SelectedObject = targetObject;
        
        // Configure based on object characteristics
        ConfigureInspection(targetObject);
    }

    private void ConfigureInspection(object target)
    {
        if (target is IComponent component)
        {
            // Enable component-specific features
            inspector.CommandsVisibleIfAvailable = true;
        }
        else
        {
            // Standard object inspection
            inspector.CommandsVisibleIfAvailable = false;
        }

        // Always show categorization for complex objects
        inspector.PropertySort = PropertySort.CategorizedAlphabetical;
        inspector.HelpVisible = true;
    }
}

Event Handling

Property Change Events

public partial class PropertyMonitor : UserControl
{
    private KryptonPropertyGrid monitoredGrid;

    public PropertyMonitor()
    {
        InitializeComponent();
        SetupEventHandling();
    }

    private void SetupEventHandling()
    {
        // Monitor property value changes
        monitoredGrid.PropertyValueChanged += OnPropertyChanged;
        
        // Monitor tab changes
        monitoredGrid.PropertyTabChanged += OnPropertyTabChanged;
        
        // Monitor sort changes
        monitoredGrid.PropertySortChanged += OnPropertySortChanged;
    }

    private void OnPropertyChanged(object? sender, PropertyValueChangedEventArgs e)
    {
        // Track property modifications
        LogPropertyChange(e.PropertyDescriptor.Name, e.OldValue, e.ChangedItem.Value);
        
        // Trigger validation if needed
        ValidateProperty(e.PropertyDescriptor, e.ChangedItem.Value);
    }

    private void OnPropertyTabChanged(object? sender, PropertyTabChangedEventArgs e)
    {
        // Handle tab switching for context-aware help
        UpdateHelpContext(e.Tab);
    }

    private void OnPropertySortChanged(object? sender, EventArgs e)
    {
        // Save user's sorting preference
        SaveSortingPreference(monitoredGrid.PropertySort);
    }
}

Custom Property Tab Integration

public class CustomPropertyTab : PropertyTab
{
    public override PropertyDescriptorCollection GetProperties(object component, Attribute[]? attributes)
    {
        var properties = TypeDescriptor.GetProperties(component);
        
        // Filter and customize properties for this tab
        var filteredProps = new List<PropertyDescriptor>();
        
        foreach (PropertyDescriptor prop in properties)
        {
            if (ShouldShowInThisTab(prop))
            {
                filteredProps.Add(prop);
            }
        }
        
        return new PropertyDescriptorCollection(filteredProps.ToArray());
    }

    public override string TabName => "Custom Tab";
}

// Usage
var propertyGrid = new KryptonPropertyGrid();
var customTab = new CustomPropertyTab();
propertyGrid.PropertyTabs?.AddTabProperty(customTab, PropertyTabScope.Component);

Performance Considerations

  • Efficient Rendering: Custom paint handling prevents flicker
  • Memory Management: Proper disposal of graphics resources
  • Theme Switching: Optimized palette switching without full recreation
  • Context Menu: Minimal overhead for enhanced context menu features

Common Issues and Solutions

Properties Not Showing

Issue: SelectedObject properties not visible
Solution: Ensure TypeConverter and Designer configuration:

[TypeConverter(typeof(ExpandableObjectConverter))]
public class MyCustomObject
{
    [Category("Appearance")]
    [Description("Visible property")]
    public string MyVisibleProperty { get; set; }
}

Theme Not Applied Correctly

Issue: Colors not matching theme
Solution: Force theme refresh:

propertyGridViewDrawPanel.Recreate();
propertyGrid.Invalidate();
UpdateStateAndPalettes();

Context Menu Reset Not Working

Issue: Reset context menu disabled unexpectedly
Solution: Ensure valid reset values:

[DefaultValue("Default Value")]
public string MyProperty { get; set; } = "Default Value";

Design-Time Integration

Visual Studio Designer

  • Designer: Custom KryptonPropertyGridDesigner provides enhanced design-time experience
  • Toolbox: Available with specialized bitmap representation
  • Property Window: Comprehensive visual state configuration
  • Containment: Properly integrates with Visual Studio's designer

Property Categories

  • Appearance: Visual properties (CommandsVisibleIfAvailable, HelpVisible, LargeButtons)
  • Behavior: Functional properties (PropertySort, SelectedObject)
  • Visuals: Theme and styling properties (StateCommon, StateNormal, AlwaysActive)

Migration from Standard PropertyGrid

Direct Replacement

// Old code
PropertyGrid propertyGrid = new PropertyGrid();

// New code
KryptonPropertyGrid propertyGrid = new KryptonPropertyGrid();

Enhanced Features

// Standard PropertyGrid (basic)
var standardPg = new PropertyGrid();

// KryptonPropertyGrid (enhanced)
var kryptonPg = new KryptonPropertyGrid
{
    ToolbarVisible = true,
    HelpVisible = true,
    PropertySort = PropertySort.CategorizedAlphabetical,
    CommandsVisibleIfAvailable = true,
    AlwaysActive = false, // Theme-aware activation
    StateNormal = // Full theme control
};

Real-World Integration Examples

Configuration Property Editor

public partial class ConfigPropertyEditor : Form
{
    private KryptonPropertyGrid configGrid;
    private Button applyButton;
    private Button resetButton;

    public ConfigPropertyEditor()
    {
        InitializeComponent();
        SetupPropertyGrid();
    }

    private void SetupPropertyGrid()
    {
        configGrid.PropertyValueChanged += OnConfigChanged;
        configGrid.ToolbarVisible = false; // Use custom buttons instead
        configGrid.HelpVisible = true; // Show descriptions
        configGrid.PropertySort = PropertySort.CategorizedAlphabetical;
    }

    public void EditConfiguration(AppConfig config)
    {
        configGrid.SelectedObject = config;
        UpdateButtonStates();
    }

    private void OnConfigChanged(object? sender, PropertyValueChangedEventArgs e)
    {
        applyButton.Enabled = true;
        resetButton.Enabled = true;
        
        // Track changes for undo functionality
        TrackConfigurationChange(e.PropertyDescriptor.Name, e.OldValue, e.ChangedItem.Value);
    }
}

Component Inspector Form

public class ComponentInspector : Form
{
    private KryptonPropertyGrid inspector;
    private ComboBox componentSelector;

    public ComponentInspector()
    {
        InitializeComponent();
    }

    public void InspectComponents(IList<IComponent> components)
    {
        // Populate component selector
        componentSelector.DataSource = components;
        componentSelector.DisplayMember = "GetType().Name";
        
        // Configure inspector for component inspection
        inspector.CommandsVisibleIfAvailable = true;
        inspector.CanShowVisualStyleGlyphs = true;
        inspector.PropertySort = PropertySort.CategorizedAlphabetical;
        
        if (components.Count > 0)
        {
            inspector.SelectedObject = components[0];
        }
    }

    private void ComponentSelector_SelectedIndexChanged(object sender, EventArgs e)
    {
        if (componentSelector.SelectedItem is IComponent selectedComponent)
        {
            inspector.SelectedObject = selectedComponent;
            UpdateComponentContext(selectedComponent);
        }
    }

    private void UpdateComponentContext(IComponent component)
    {
        // Update title and context based on selected component
        Text = $"Inspecting {component.GetType().Name}";
        
        // Configure visual state based on component type
        if (component is Control control)
        {
            inspector.AlwaysActive = control.ContainsFocus;
        }
        else
        {
            inspector.AlwaysActive = false;
        }
    }
}
Back to top Krypton Component Suite 2024 BSD 3-Clause License © Component Factory Pty Ltd, 2006 - 2016, All rights reserved. Modifications by Peter Wagner (aka Wagnerp), Simon Coghlan (aka Smurf-IV), Giduac, Tobitege, Lesarndro, KamaniAR & Ahmed Abdelhameed et al. 2017 - 2025. All rights reserved. https://github.com/Krypton-Suite