7.0 KiB
7.0 KiB
PropertyGrid Quick Reference Guide
Essential Attributes
Display Attribute
Controls property appearance in PropertyGrid:
[Display(
Name = "Display Name", // Shown in UI
Description = "Property help", // Tooltip/description
Order = 1 // Sort order in category
)]
public string MyProperty { get; set; }
Category Attribute
Groups related properties:
[Category("Server Settings")]
public string ServerName { get; set; }
ReadOnly Attribute
Makes property non-editable:
[ReadOnly(true)]
public string ComputedValue { get; set; }
Validation Attributes
Required
[Required(ErrorMessage = "This field is required")]
public string ServerName { get; set; }
Range
[Range(1, 100, ErrorMessage = "Value must be between 1 and 100")]
public int Connections { get; set; }
StringLength
[StringLength(50, MinimumLength = 3,
ErrorMessage = "Length must be between 3 and 50")]
public string Name { get; set; }
RegularExpression
[RegularExpression(@"^\d{3}-\d{2}-\d{4}$",
ErrorMessage = "Invalid format")]
public string SSN { get; set; }
Special Attributes
PasswordPropertyText
Hides text input:
[PasswordPropertyText(true)]
public string Password { get; set; }
EditorBrowsable
Controls visibility of advanced properties:
[EditorBrowsable(EditorBrowsableState.Advanced)]
public string AdvancedSetting { get; set; }
INotifyPropertyChanged Pattern
Basic Implementation
public class MyModel : INotifyPropertyChanged
{
private string _name = string.Empty;
public string Name
{
get => _name;
set
{
if (_name != value)
{
_name = value;
OnPropertyChanged();
}
}
}
public event PropertyChangedEventHandler? PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string? name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
Helper Method Pattern
protected bool SetProperty<T>(ref T field, T value,
[CallerMemberName] string? propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value))
return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}
// Usage
public string Name
{
get => _name;
set => SetProperty(ref _name, value);
}
Supported Property Types
Basic Types
string- Text inputint,long,short- Numeric inputdouble,float,decimal- Decimal inputbool- CheckboxDateTime- Date/time pickerTimeSpan- Duration inputGuid- GUID inputUri- URL input
Complex Types
enum- Dropdown list- Nested objects - Expandable group
List<T>- Collection editor (if supported)
Nullable Types
All value types can be nullable:
public int? OptionalNumber { get; set; }
public DateTime? OptionalDate { get; set; }
Enum with Descriptions
public enum Status
{
[Description("Not yet started")]
NotStarted,
[Description("Currently in progress")]
InProgress,
[Description("Successfully completed")]
Completed,
[Description("Failed with errors")]
Failed
}
Nested Objects
public class Configuration
{
[Display(Name = "Database Settings")]
[Category("Database")]
public DatabaseSettings Database { get; set; } = new();
}
public class DatabaseSettings
{
[Display(Name = "Server")]
public string Server { get; set; } = "localhost";
[Display(Name = "Port")]
[Range(1, 65535)]
public int Port { get; set; } = 5432;
}
XAML Setup
Basic PropertyGrid
<Window xmlns:pg="using:Avalonia.PropertyGrid.Controls"
xmlns:models="using:YourNamespace.Models"
x:DataType="models:YourModel">
<pg:PropertyGrid SelectedObject="{Binding}"
ShowCategories="True"
ShowDescriptions="True" />
</Window>
Code-Behind
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new YourModel();
}
}
Computed Properties
Properties that derive from other properties:
private bool _isEnabled;
public bool IsEnabled
{
get => _isEnabled;
set
{
if (SetProperty(ref _isEnabled, value))
{
OnPropertyChanged(nameof(StatusText));
}
}
}
[ReadOnly(true)]
public string StatusText => IsEnabled ? "Enabled" : "Disabled";
Common Patterns
Server Configuration
[Display(Name = "Server Address", Order = 1)]
[Category("Connection")]
[Required]
public string ServerAddress { get; set; } = "localhost";
[Display(Name = "Port", Order = 2)]
[Category("Connection")]
[Range(1, 65535)]
public int Port { get; set; } = 8080;
[Display(Name = "Use SSL", Order = 3)]
[Category("Security")]
public bool UseSsl { get; set; } = true;
Credentials
[Display(Name = "Username")]
[Category("Authentication")]
[Required]
public string Username { get; set; } = string.Empty;
[Display(Name = "Password")]
[Category("Authentication")]
[PasswordPropertyText(true)]
public string Password { get; set; } = string.Empty;
File Paths
[Display(Name = "Log Directory")]
[Category("Logging")]
[EditorBrowsable(EditorBrowsableState.Advanced)]
public string LogDirectory { get; set; } = @"C:\Logs\";
Tips & Tricks
1. Property Order Gaps
Use gaps (10, 20, 30) for easy insertion:
[Display(Order = 10)] // Easy to insert Order = 15 later
[Display(Order = 20)]
[Display(Order = 30)]
2. Category Naming
Use clear, hierarchical names:
- ✅ "Server Configuration"
- ✅ "Database / Connection"
- ❌ "Misc"
- ❌ "Settings"
3. Meaningful Descriptions
// ❌ Bad
[Display(Description = "The timeout")]
// ✅ Good
[Display(Description = "Connection timeout in seconds (1-300)")]
4. Validation Messages
// ❌ Generic
[Required(ErrorMessage = "Required")]
// ✅ Specific
[Required(ErrorMessage = "Server name is required for connection")]
5. Default Values
Always provide sensible defaults:
public int MaxConnections { get; set; } = 100; // ✅ Good default
public int Timeout { get; set; } = 30; // ✅ Reasonable
public string Server { get; set; } = string.Empty; // ✅ Safe default
Debugging
Check Binding
Add this to see binding errors:
.LogToTrace(areas: new[] {
LogArea.Binding,
LogArea.Property
})
Verify DataContext
public MainWindow()
{
InitializeComponent();
var model = new MyModel();
DataContext = model;
// Verify
System.Diagnostics.Debug.WriteLine($"DataContext: {DataContext?.GetType().Name}");
}
Performance
Lazy Loading
private DatabaseSettings? _database;
public DatabaseSettings Database => _database ??= new DatabaseSettings();
Efficient Notifications
// Only notify if value actually changed
if (_field == value) return;
See Also
- QuickStartExample - Basic usage
- AdvancedExample - Complex scenarios
- Technical Documentation - Deep dive
Need help? Check the examples or review the PropertyGrid source code!