Files
PropertyGrid/Examples/QUICK_REFERENCE.md
T
2026-08-10 14:46:18 +02:00

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 input
  • int, long, short - Numeric input
  • double, float, decimal - Decimal input
  • bool - Checkbox
  • DateTime - Date/time picker
  • TimeSpan - Duration input
  • Guid - GUID input
  • Uri - 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


Need help? Check the examples or review the PropertyGrid source code!