diff --git a/Avalonia.PropertyGrid/Controls/PropertyGrid.axaml b/Avalonia.PropertyGrid/Controls/PropertyGrid.axaml index 6968dda..c097ad6 100644 --- a/Avalonia.PropertyGrid/Controls/PropertyGrid.axaml +++ b/Avalonia.PropertyGrid/Controls/PropertyGrid.axaml @@ -4,361 +4,375 @@ xmlns:models="using:Avalonia.PropertyGrid.Models" xmlns:sys="clr-namespace:System;assembly=System.Runtime"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Avalonia.PropertyGrid/Controls/PropertyGrid.axaml.cs b/Avalonia.PropertyGrid/Controls/PropertyGrid.axaml.cs index 14ad537..e33095c 100644 --- a/Avalonia.PropertyGrid/Controls/PropertyGrid.axaml.cs +++ b/Avalonia.PropertyGrid/Controls/PropertyGrid.axaml.cs @@ -288,11 +288,10 @@ public class PropertyGrid : TemplatedControl // Apply search filter if (!string.IsNullOrWhiteSpace(_searchText)) { - var searchLower = _searchText.ToLowerInvariant(); filtered = filtered.Where(p => - p.DisplayName.ToLowerInvariant().Contains(searchLower) || - (p.Category?.ToLowerInvariant().Contains(searchLower) ?? false) || - (p.Description?.ToLowerInvariant().Contains(searchLower) ?? false)); + p.DisplayName.Contains(_searchText, StringComparison.OrdinalIgnoreCase) || + (p.Category?.Contains(_searchText, StringComparison.OrdinalIgnoreCase) ?? false) || + (p.Description?.Contains(_searchText, StringComparison.OrdinalIgnoreCase) ?? false)); } // Populate flat list diff --git a/Avalonia.PropertyGrid/Converters/ColorToBrushConverter.cs b/Avalonia.PropertyGrid/Converters/ColorToBrushConverter.cs index 0743063..51bf4d2 100644 --- a/Avalonia.PropertyGrid/Converters/ColorToBrushConverter.cs +++ b/Avalonia.PropertyGrid/Converters/ColorToBrushConverter.cs @@ -8,8 +8,16 @@ namespace Avalonia.PropertyGrid.Controls; /// /// Converts an Avalonia.Media.Color to a SolidColorBrush /// -public class ColorToBrushConverter : IValueConverter +public sealed class ColorToBrushConverter : IValueConverter { + /// + /// Converts a Color to a SolidColorBrush. + /// + /// The Color value to convert. + /// The target type. + /// Optional parameter. + /// Culture information. + /// A SolidColorBrush with the specified color. public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) { if (value is Color color) @@ -21,9 +29,17 @@ public class ColorToBrushConverter : IValueConverter return new SolidColorBrush(Colors.Transparent); } + /// + /// Converts a SolidColorBrush back to a Color. + /// + /// The SolidColorBrush value to convert back. + /// The target type. + /// Optional parameter. + /// Culture information. + /// The Color from the brush. public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) { - if (value is SolidColorBrush brush && brush.Color != null) + if (value is SolidColorBrush brush) { return brush.Color; } diff --git a/Avalonia.PropertyGrid/Converters/NegateBoolConverter.cs b/Avalonia.PropertyGrid/Converters/NegateBoolConverter.cs index 71f5744..fb42d44 100644 --- a/Avalonia.PropertyGrid/Converters/NegateBoolConverter.cs +++ b/Avalonia.PropertyGrid/Converters/NegateBoolConverter.cs @@ -7,8 +7,16 @@ namespace Avalonia.PropertyGrid.Controls; /// /// Converts boolean value to its negation for two-way binding /// -public class NegateBoolConverter : IValueConverter +public sealed class NegateBoolConverter : IValueConverter { + /// + /// Converts a boolean value to its negation. + /// + /// The boolean value to convert. + /// The target type. + /// Optional parameter. + /// Culture information. + /// The negated boolean value. public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) { if (value is bool boolValue) @@ -18,6 +26,14 @@ public class NegateBoolConverter : IValueConverter return false; } + /// + /// Converts a boolean value back to its negation (two-way binding). + /// + /// The boolean value to convert back. + /// The target type. + /// Optional parameter. + /// Culture information. + /// The negated boolean value. public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) { if (value is bool boolValue) diff --git a/Avalonia.PropertyGrid/Converters/NumericFormatConverter.cs b/Avalonia.PropertyGrid/Converters/NumericFormatConverter.cs index c56fcbc..d0f6c98 100644 --- a/Avalonia.PropertyGrid/Converters/NumericFormatConverter.cs +++ b/Avalonia.PropertyGrid/Converters/NumericFormatConverter.cs @@ -7,8 +7,16 @@ namespace Avalonia.PropertyGrid.Controls; /// /// Converts PropertyType to appropriate numeric format string /// -public class NumericFormatConverter : IValueConverter +public sealed class NumericFormatConverter : IValueConverter { + /// + /// Converts a Type to an appropriate numeric format string. + /// + /// The Type to convert. + /// The target type. + /// Optional parameter. + /// Culture information. + /// A format string like "N2" for floating point or "N0" for integers. public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) { if (value is Type type) @@ -26,6 +34,15 @@ public class NumericFormatConverter : IValueConverter return "N0"; } + /// + /// Not supported for this converter. + /// + /// The value to convert back. + /// The target type. + /// Optional parameter. + /// Culture information. + /// Throws NotImplementedException. + /// This converter does not support ConvertBack. public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) { throw new NotImplementedException(); diff --git a/Avalonia.PropertyGrid/Converters/PropertyGridConverters.cs b/Avalonia.PropertyGrid/Converters/PropertyGridConverters.cs index df8239b..20f398c 100644 --- a/Avalonia.PropertyGrid/Converters/PropertyGridConverters.cs +++ b/Avalonia.PropertyGrid/Converters/PropertyGridConverters.cs @@ -7,7 +7,7 @@ namespace Avalonia.PropertyGrid.Controls; /// /// Converts indent level to left margin /// -public class IndentToMarginConverter : IValueConverter +public sealed class IndentToMarginConverter : IValueConverter { /// /// Converts indent level to left margin. @@ -33,7 +33,7 @@ public class IndentToMarginConverter : IValueConverter /// /// Converts enum type to list of enum values /// -public class EnumValuesConverter : IValueConverter +public sealed class EnumValuesConverter : IValueConverter { /// /// Converts an enum type to an array of its values. @@ -59,8 +59,16 @@ public class EnumValuesConverter : IValueConverter /// /// Checks if a type is an enum /// -public class IsEnumConverter : IValueConverter +public sealed class IsEnumConverter : IValueConverter { + /// + /// Checks if the provided type is an enum. + /// + /// The Type to check. + /// The target type. + /// Optional parameter. + /// Culture information. + /// True if the type is an enum, otherwise false. public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) { if (value is Type type) @@ -70,6 +78,10 @@ public class IsEnumConverter : IValueConverter return false; } + /// + /// Not supported for this converter. + /// + /// This converter does not support ConvertBack. public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) { throw new NotImplementedException(); @@ -79,8 +91,16 @@ public class IsEnumConverter : IValueConverter /// /// Checks if a type is a simple type (string, number, bool, etc.) /// -public class IsSimpleTypeConverter : IValueConverter +public sealed class IsSimpleTypeConverter : IValueConverter { + /// + /// Checks if the provided type is a simple type like string, number, DateTime, etc. + /// + /// The Type to check. + /// The target type. + /// Optional parameter. + /// Culture information. + /// True if the type is a simple type, otherwise false. public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) { if (value is Type type) @@ -96,6 +116,10 @@ public class IsSimpleTypeConverter : IValueConverter return false; } + /// + /// Not supported for this converter. + /// + /// This converter does not support ConvertBack. public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) { throw new NotImplementedException(); @@ -105,8 +129,16 @@ public class IsSimpleTypeConverter : IValueConverter /// /// Checks if a type matches the specified type name /// -public class TypeToBoolConverter : IValueConverter +public sealed class TypeToBoolConverter : IValueConverter { + /// + /// Checks if the type's name matches the specified parameter string. + /// + /// The Type to check. + /// The target type. + /// The type name to match against. + /// Culture information. + /// True if the type name matches, otherwise false. public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) { if (value is Type type && parameter is string typeName) @@ -116,6 +148,10 @@ public class TypeToBoolConverter : IValueConverter return false; } + /// + /// Not supported for this converter. + /// + /// This converter does not support ConvertBack. public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) { throw new NotImplementedException(); @@ -125,8 +161,16 @@ public class TypeToBoolConverter : IValueConverter /// /// Converts Color to/from hex string representation /// -public class ColorToStringConverter : IValueConverter +public sealed class ColorToStringConverter : IValueConverter { + /// + /// Converts a Color to a hex string representation. + /// + /// The Color to convert. + /// The target type. + /// Optional parameter. + /// Culture information. + /// A hex string representation of the color (e.g., "#AARRGGBB"). public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) { if (value is Media.Color color) @@ -136,6 +180,14 @@ public class ColorToStringConverter : IValueConverter return value?.ToString(); } + /// + /// Converts a hex string back to a Color. + /// + /// The hex string to convert. + /// The target type. + /// Optional parameter. + /// Culture information. + /// The parsed Color, or Black if parsing fails. public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) { if (value is string hexString && !string.IsNullOrWhiteSpace(hexString)) @@ -143,7 +195,7 @@ public class ColorToStringConverter : IValueConverter try { hexString = hexString.Trim(); - if (!hexString.StartsWith("#")) + if (!hexString.StartsWith('#')) hexString = "#" + hexString; return Media.Color.Parse(hexString); @@ -161,8 +213,16 @@ public class ColorToStringConverter : IValueConverter /// /// Checks if a type is Color /// -public class IsColorTypeConverter : IValueConverter +public sealed class IsColorTypeConverter : IValueConverter { + /// + /// Checks if the provided type is Avalonia.Media.Color. + /// + /// The Type to check. + /// The target type. + /// Optional "Invert" parameter to invert the result. + /// Culture information. + /// True if the type is Color (or inverted if parameter is "Invert"), otherwise false. public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) { if (value is Type type) @@ -187,6 +247,10 @@ public class IsColorTypeConverter : IValueConverter return false; } + /// + /// Not supported for this converter. + /// + /// This converter does not support ConvertBack. public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) { throw new NotImplementedException(); @@ -196,8 +260,16 @@ public class IsColorTypeConverter : IValueConverter /// /// Checks if a type is numeric /// -public class IsNumericTypeConverter : IValueConverter +public sealed class IsNumericTypeConverter : IValueConverter { + /// + /// Checks if the provided type is a numeric type (int, long, float, double, decimal, etc.). + /// + /// The Type to check. + /// The target type. + /// Optional "Invert" parameter to invert the result. + /// Culture information. + /// True if the type is numeric (or inverted if parameter is "Invert"), otherwise false. public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) { if (value is Type type) @@ -225,6 +297,10 @@ public class IsNumericTypeConverter : IValueConverter return false; } + /// + /// Not supported for this converter. + /// + /// This converter does not support ConvertBack. public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) { throw new NotImplementedException(); @@ -234,8 +310,16 @@ public class IsNumericTypeConverter : IValueConverter /// /// Checks if a type is neither Color nor Numeric nor Boolean nor Enum (for fallback TextBox) /// -public class IsOtherTypeConverter : IValueConverter +public sealed class IsOtherTypeConverter : IValueConverter { + /// + /// Checks if the type is not Color, Numeric, Boolean, or Enum (used for fallback TextBox editor). + /// + /// The Type to check. + /// The target type. + /// Optional parameter. + /// Culture information. + /// True if the type is not a special type, otherwise false. public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) { if (value is Type type) @@ -255,6 +339,10 @@ public class IsOtherTypeConverter : IValueConverter return true; // Default to showing TextBox } + /// + /// Not supported for this converter. + /// + /// This converter does not support ConvertBack. public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) { throw new NotImplementedException(); @@ -264,8 +352,16 @@ public class IsOtherTypeConverter : IValueConverter /// /// Checks if a type is boolean /// -public class IsBooleanTypeConverter : IValueConverter +public sealed class IsBooleanTypeConverter : IValueConverter { + /// + /// Checks if the provided type is boolean. + /// + /// The Type to check. + /// The target type. + /// Optional "Invert" parameter to invert the result. + /// Culture information. + /// True if the type is boolean (or inverted if parameter is "Invert"), otherwise false. public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) { if (value is Type type) @@ -290,6 +386,10 @@ public class IsBooleanTypeConverter : IValueConverter return false; } + /// + /// Not supported for this converter. + /// + /// This converter does not support ConvertBack. public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) { throw new NotImplementedException(); diff --git a/Avalonia.PropertyGrid/Editors/PropertyEditors.cs b/Avalonia.PropertyGrid/Editors/PropertyEditors.cs index 12d7d4b..51c3918 100644 --- a/Avalonia.PropertyGrid/Editors/PropertyEditors.cs +++ b/Avalonia.PropertyGrid/Editors/PropertyEditors.cs @@ -266,7 +266,7 @@ public class DateTimeEditor : PropertyEditor /// /// Converter for DateTime to DateTimeOffset /// -internal class DateTimeToDateTimeOffsetConverter : Avalonia.Data.Converters.IValueConverter +internal sealed class DateTimeToDateTimeOffsetConverter : Avalonia.Data.Converters.IValueConverter { public object? Convert(object? value, Type targetType, object? parameter, System.Globalization.CultureInfo culture) { diff --git a/Avalonia.PropertyGrid/Models/CategoryGroup.cs b/Avalonia.PropertyGrid/Models/CategoryGroup.cs index 11e2a03..e27b48d 100644 --- a/Avalonia.PropertyGrid/Models/CategoryGroup.cs +++ b/Avalonia.PropertyGrid/Models/CategoryGroup.cs @@ -47,6 +47,10 @@ public class CategoryGroup : INotifyPropertyChanged /// public int PropertyCount => Properties.Count; + /// + /// Raises the PropertyChanged event for the specified property. + /// + /// The name of the property that changed. protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); diff --git a/Avalonia.PropertyGrid/Models/PropertyItem.cs b/Avalonia.PropertyGrid/Models/PropertyItem.cs index 9a4858b..dcac68a 100644 --- a/Avalonia.PropertyGrid/Models/PropertyItem.cs +++ b/Avalonia.PropertyGrid/Models/PropertyItem.cs @@ -182,7 +182,7 @@ public class PropertyItem : INotifyPropertyChanged try { var hexString = value?.Trim() ?? ""; - if (!hexString.StartsWith("#")) + if (!hexString.StartsWith('#')) hexString = "#" + hexString; Value = Media.Color.Parse(hexString); diff --git a/Examples/AdvancedExample/Models/AdvancedConfiguration.cs b/Examples/AdvancedExample/Models/AdvancedConfiguration.cs index ffed645..d469637 100644 --- a/Examples/AdvancedExample/Models/AdvancedConfiguration.cs +++ b/Examples/AdvancedExample/Models/AdvancedConfiguration.cs @@ -223,7 +223,7 @@ public class NetworkSettings : INotifyPropertyChanged { private string _hostname = "api.example.com"; private int _port = 443; - private bool _useProxy = false; + private bool _useProxy; private string _proxyAddress = string.Empty; [Display(Name = "Hostname", Description = "Server hostname or IP address")] diff --git a/Examples/AdvancedExample/Program.cs b/Examples/AdvancedExample/Program.cs index 02f182d..c4f296c 100644 --- a/Examples/AdvancedExample/Program.cs +++ b/Examples/AdvancedExample/Program.cs @@ -3,7 +3,7 @@ using System; namespace AdvancedExample; -class Program +sealed class Program { [STAThread] public static void Main(string[] args) => BuildAvaloniaApp() diff --git a/Examples/QuickStartExample/Program.cs b/Examples/QuickStartExample/Program.cs index 5c49989..43fe402 100644 --- a/Examples/QuickStartExample/Program.cs +++ b/Examples/QuickStartExample/Program.cs @@ -3,7 +3,7 @@ using Avalonia; namespace QuickStartExample; -class Program +sealed class Program { [STAThread] public static void Main(string[] args) => BuildAvaloniaApp() diff --git a/PropertyGrid.slnx b/PropertyGrid.slnx new file mode 100644 index 0000000..70d6cf6 --- /dev/null +++ b/PropertyGrid.slnx @@ -0,0 +1,7 @@ + + + + + + +