283 lines
8.0 KiB
Markdown
283 lines
8.0 KiB
Markdown
# Avalonia PropertyGrid Control
|
|||
|
|
|
||
|
|
A powerful PropertyGrid control for Avalonia UI with Xceed PropertyGrid-like functionality, built with .NET 10 and C#.
|
||
|
|
|
||
|
|
## ✅ Project Status
|
||
|
|
|
||
|
|
**Successfully Implemented and Building:**
|
||
|
|
- ✅ Avalonia.PropertyGrid (Core Library)
|
||
|
|
- ✅ PropertyGridExample (Main Demo Application)
|
||
|
|
|
||
|
|
## Features
|
||
|
|
|
||
|
|
✓ **Category Grouping** - Organize properties into logical categories
|
||
|
|
✓ **Property Descriptions** - Show helpful tooltips and descriptions
|
||
|
|
✓ **Search/Filter** - Quickly find properties with real-time filtering
|
||
|
|
✓ **Read-Only Properties** - Support for non-editable properties
|
||
|
|
✓ **Multiple Data Types** - Built-in editors for strings, numbers, booleans, enums, dates
|
||
|
|
✓ **Nested Objects** - Expandable complex property types
|
||
|
|
✓ **Custom Editors** - Extensible editor system for custom types
|
||
|
|
✓ **Type Converters** - Integration with .NET TypeConverter system
|
||
|
|
✓ **MVVM-Friendly** - Designed for data binding and MVVM patterns
|
||
|
|
✓ **Attribute-Based** - Uses standard .NET attributes (Display, Category, ReadOnly, Browsable, etc.)
|
||
|
|
|
||
|
|
## Solution Structure
|
||
|
|
|
||
|
|
```
|
||
|
|
PropertyGridExample/
|
||
|
|
├── Avalonia.PropertyGrid/ # Core PropertyGrid library ✅
|
||
|
|
│ ├── Controls/
|
||
|
|
│ │ ├── PropertyGrid.axaml # Main control XAML
|
||
|
|
│ │ └── PropertyGrid.axaml.cs # Control implementation
|
||
|
|
│ ├── Models/
|
||
|
|
│ │ ├── PropertyItem.cs # Property metadata model
|
||
|
|
│ │ └── PropertyCategory.cs # Category grouping
|
||
|
|
│ ├── Services/
|
||
|
|
│ │ └── PropertyItemFactory.cs # Property reflection service
|
||
|
|
│ ├── Editors/
|
||
|
|
│ │ ├── PropertyEditors.cs # Built-in editors
|
||
|
|
│ │ └── EditorRegistry.cs # Custom editor registration
|
||
|
|
│ └── Converters/
|
||
|
|
│ └── PropertyGridConverters.cs # Value converters
|
||
|
|
│
|
||
|
|
└── PropertyGridExample/ # Main comprehensive demo ✅
|
||
|
|
└── Models/DemoObject.cs # Example model with properties
|
||
|
|
```
|
||
|
|
|
||
|
|
## Getting Started
|
||
|
|
|
||
|
|
### Running the Demo
|
||
|
|
|
||
|
|
1. Open the solution in Visual Studio 2026
|
||
|
|
2. Set **PropertyGridExample** as the startup project
|
||
|
|
3. Press **F5** to run
|
||
|
|
|
||
|
|
Or use the command line:
|
||
|
|
```bash
|
||
|
|
dotnet run --project PropertyGridExample
|
||
|
|
```
|
||
|
|
|
||
|
|
### Using the PropertyGrid in Your Project
|
||
|
|
|
||
|
|
#### 1. Add Project Reference
|
||
|
|
|
||
|
|
Add a reference to the Avalonia.PropertyGrid library in your `.csproj`:
|
||
|
|
|
||
|
|
```xml
|
||
|
|
<ItemGroup>
|
||
|
|
<ProjectReference Include="..\Avalonia.PropertyGrid\Avalonia.PropertyGrid.csproj" />
|
||
|
|
</ItemGroup>
|
||
|
|
```
|
||
|
|
|
||
|
|
#### 2. Add XAML Namespace
|
||
|
|
|
||
|
|
In your XAML file:
|
||
|
|
|
||
|
|
```xml
|
||
|
|
<Window xmlns:pg="using:Avalonia.PropertyGrid.Controls"
|
||
|
|
...>
|
||
|
|
```
|
||
|
|
|
||
|
|
#### 3. Use the PropertyGrid Control
|
||
|
|
|
||
|
|
```xml
|
||
|
|
<pg:PropertyGrid Name="PropertyGrid"
|
||
|
|
SelectedObject="{Binding YourObject}"
|
||
|
|
ShowCategories="True"
|
||
|
|
ShowDescriptions="True" />
|
||
|
|
```
|
||
|
|
|
||
|
|
#### 4. Decorate Your Model Classes
|
||
|
|
|
||
|
|
Use standard .NET attributes:
|
||
|
|
|
||
|
|
```csharp
|
||
|
|
using System.ComponentModel;
|
||
|
|
using System.ComponentModel.DataAnnotations;
|
||
|
|
|
||
|
|
public class Person
|
||
|
|
{
|
||
|
|
[Display(Name = "First Name", Description = "The person's first name", Order = 1)]
|
||
|
|
[Category("Personal Information")]
|
||
|
|
public string FirstName { get; set; } = "John";
|
||
|
|
|
||
|
|
[Display(Name = "Age", Description = "Age in years", Order = 2)]
|
||
|
|
[Category("Personal Information")]
|
||
|
|
public int Age { get; set; } = 30;
|
||
|
|
|
||
|
|
[ReadOnly(true)]
|
||
|
|
public string ID { get; set; } = Guid.NewGuid().ToString();
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Supported Attributes
|
||
|
|
|
||
|
|
The PropertyGrid recognizes these standard .NET attributes:
|
||
|
|
|
||
|
|
- **`[Display]`** - Set display name, description, order, and group
|
||
|
|
- **`[Category]`** - Group properties into categories
|
||
|
|
- **`[DisplayName]`** - Alternative to Display for setting display name
|
||
|
|
- **`[Description]`** - Property description for tooltips
|
||
|
|
- **`[ReadOnly]`** - Make property non-editable
|
||
|
|
- **`[Browsable]`** - Hide properties from the grid
|
||
|
|
- **TypeConverter** - Custom value conversion
|
||
|
|
|
||
|
|
## Built-In Property Editors
|
||
|
|
|
||
|
|
The PropertyGrid includes editors for common types:
|
||
|
|
|
||
|
|
- **String** - TextBox editor
|
||
|
|
- **Numeric Types** - NumericUpDown (int, long, double, float, decimal, etc.)
|
||
|
|
- **Boolean** - CheckBox
|
||
|
|
- **Enum** - ComboBox with all enum values
|
||
|
|
- **DateTime** - DatePicker
|
||
|
|
- **Complex Objects** - Expandable nested properties (when implemented)
|
||
|
|
|
||
|
|
## API Reference
|
||
|
|
|
||
|
|
### PropertyGrid Properties
|
||
|
|
|
||
|
|
- **`SelectedObject`** (object?) - The object whose properties are displayed
|
||
|
|
- **`SearchText`** (string) - Filter text for searching properties
|
||
|
|
- **`ShowCategories`** (bool) - Whether to show category grouping
|
||
|
|
- **`ShowDescriptions`** (bool) - Whether to show property descriptions
|
||
|
|
- **`FilteredProperties`** (ObservableCollection<PropertyItem>) - The filtered collection of properties
|
||
|
|
|
||
|
|
### PropertyGrid Methods
|
||
|
|
|
||
|
|
- **`RefreshProperties()`** - Reload properties from the selected object
|
||
|
|
- **`RefreshValues()`** - Update property values from the source
|
||
|
|
|
||
|
|
## Creating Custom Editors
|
||
|
|
|
||
|
|
### 1. Create Your Editor
|
||
|
|
|
||
|
|
Inherit from `PropertyEditor` base class:
|
||
|
|
|
||
|
|
```csharp
|
||
|
|
using Avalonia.PropertyGrid.Editors;
|
||
|
|
using Avalonia.PropertyGrid.Models;
|
||
|
|
|
||
|
|
public class ColorEditor : PropertyEditor
|
||
|
|
{
|
||
|
|
private ColorPicker? _colorPicker;
|
||
|
|
|
||
|
|
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||
|
|
{
|
||
|
|
base.OnApplyTemplate(e);
|
||
|
|
_colorPicker = new ColorPicker();
|
||
|
|
Content = _colorPicker;
|
||
|
|
}
|
||
|
|
|
||
|
|
protected override void BindToProperty(PropertyItem item)
|
||
|
|
{
|
||
|
|
if (_colorPicker != null)
|
||
|
|
{
|
||
|
|
_colorPicker.Bind(ColorPicker.ColorProperty,
|
||
|
|
new Binding(nameof(PropertyItem.Value))
|
||
|
|
{
|
||
|
|
Source = item,
|
||
|
|
Mode = BindingMode.TwoWay
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
protected override void UnbindFromProperty(PropertyItem item)
|
||
|
|
{
|
||
|
|
_colorPicker?.ClearValue(ColorPicker.ColorProperty);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2. Register Your Editor
|
||
|
|
|
||
|
|
```csharp
|
||
|
|
using Avalonia.PropertyGrid.Editors;
|
||
|
|
using Avalonia.Media;
|
||
|
|
|
||
|
|
// Register for all Color properties
|
||
|
|
EditorRegistry.RegisterEditor(typeof(Color), typeof(ColorEditor));
|
||
|
|
|
||
|
|
// Or register for specific property names
|
||
|
|
EditorRegistry.RegisterEditor("PrimaryColor", typeof(ColorEditor));
|
||
|
|
```
|
||
|
|
|
||
|
|
## Requirements
|
||
|
|
|
||
|
|
- **.NET 10.0** - Latest .NET version
|
||
|
|
- **Avalonia UI 12.1.0** - Modern cross-platform UI framework
|
||
|
|
- **C# 13** - Latest language features
|
||
|
|
- **Visual Studio 2026** or **JetBrains Rider** (recommended)
|
||
|
|
|
||
|
|
## Building the Solution
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Restore packages
|
||
|
|
dotnet restore
|
||
|
|
|
||
|
|
# Build all projects
|
||
|
|
dotnet build
|
||
|
|
|
||
|
|
# Run the demo
|
||
|
|
dotnet run --project PropertyGridExample
|
||
|
|
```
|
||
|
|
|
||
|
|
## Architecture
|
||
|
|
|
||
|
|
### Core Components
|
||
|
|
|
||
|
|
**PropertyGrid Control**
|
||
|
|
- Main UI control that hosts the property list
|
||
|
|
- Handles search/filtering
|
||
|
|
- Manages property item display
|
||
|
|
|
||
|
|
**PropertyItem Model**
|
||
|
|
- Represents a single property with metadata
|
||
|
|
- Supports nested properties
|
||
|
|
- Implements INotifyPropertyChanged for data binding
|
||
|
|
|
||
|
|
**PropertyItemFactory**
|
||
|
|
- Uses reflection to discover properties
|
||
|
|
- Reads .NET attributes for metadata
|
||
|
|
- Creates PropertyItem instances
|
||
|
|
|
||
|
|
**Editor System**
|
||
|
|
- Built-in editors for common types
|
||
|
|
- EditorRegistry for custom editor registration
|
||
|
|
- PropertyEditor base class for extensibility
|
||
|
|
|
||
|
|
## Known Limitations
|
||
|
|
|
||
|
|
- Example projects (BasicExample, AdvancedExample, CustomEditorsExample) have XAML compilation issues and are not included in the solution
|
||
|
|
- The main PropertyGridExample demonstrates all core functionality
|
||
|
|
- Type-based editor selection via XAML selectors was simplified due to Avalonia limitations
|
||
|
|
- Editor selection can be enhanced by implementing a custom DataTemplateSelector
|
||
|
|
|
||
|
|
## Future Enhancements
|
||
|
|
|
||
|
|
Potential improvements:
|
||
|
|
- ✨ Add validation support with IDataErrorInfo
|
||
|
|
- ✨ Implement undo/redo functionality
|
||
|
|
- ✨ Add collection/array editor support
|
||
|
|
- ✨ Enhance nested object editing
|
||
|
|
- ✨ Add property grouping options
|
||
|
|
- ✨ Implement property value change events
|
||
|
|
- ✨ Add keyboard navigation support
|
||
|
|
- ✨ Create additional built-in editors (file picker, folder picker, etc.)
|
||
|
|
|
||
|
|
## Contributing
|
||
|
|
|
||
|
|
Feel free to extend and customize the PropertyGrid:
|
||
|
|
- Add more built-in editors
|
||
|
|
- Enhance UI styling with custom themes
|
||
|
|
- Implement advanced features
|
||
|
|
- Fix any issues you encounter
|
||
|
|
|
||
|
|
## License
|
||
|
|
|
||
|
|
This project is provided as-is for demonstration and educational purposes.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
**Built with ❤️ using Avalonia UI 12.1.0 and .NET 10**
|