< Summary - PropertyGridHelpers Code Coverage

Information
Class: PropertyGridHelpers.Attributes.AllowBlankAttribute
Assembly: PropertyGridHelpers
File(s): c:\agent\_work\9\s\Code\PropertyGridHelpers\Attributes\AllowBlankAttribute.cs
Tag: PropertyGridHelpers Build_2025.7.15.1_#485
Line coverage
100%
Covered lines: 52
Uncovered lines: 0
Coverable lines: 52
Total lines: 198
Line coverage: 100%
Branch coverage
100%
Covered branches: 32
Total branches: 32
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100

Metrics

MethodBlocks covered Blocks not covered Branch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)--100%11100%
AllowBlankAttribute(...)20----
get_Allow()--100%11100%
get_IncludeItem()--100%11100%
get_ResourceItem()--100%11100%
IsBlankAllowed(...)70100%22100%
IsBlankAllowed(...)50----
GetBlankLabel(...)620100%2424100%
GetBlankLabel(...)500----
Get(...)100100%66100%
ToString()50100%11100%

File(s)

c:\agent\_work\9\s\Code\PropertyGridHelpers\Attributes\AllowBlankAttribute.cs

#LineLine coverage
 1using PropertyGridHelpers.Converters;
 2using PropertyGridHelpers.UIEditors;
 3using System;
 4using System.ComponentModel;
 5using System.Globalization;
 6using System.Linq;
 7
 8namespace PropertyGridHelpers.Attributes
 9{
 10#if NET8_0_OR_GREATER
 11    /// <summary>
 12    /// Specifies whether a blank (empty) value is allowed for a property, typically used in dropdown editors.
 13    /// </summary>
 14    /// <param name="allow">if set to <c>true</c> allow blank values in the property.</param>
 15    /// <param name="includeItem">if set to <c>true</c> include item in the dropdown to indicate blank.</param>
 16    /// <param name="resourceItem">The resource item to use for displaying the blank item (Leaves it empty when this is 
 17    /// <remarks>
 18    /// This attribute is used in conjunction with editors like <see cref="ResourcePathEditor"/> and converters
 19    /// like <see cref="OnlySelectableTypeConverter"/> to optionally include a blank entry in the list of selectable val
 20    /// </remarks>
 21    /// <example>
 22    /// <code language="csharp">
 23    /// [AllowBlank(includeItem: true, resourceItem: "Blank_DisplayText")]
 24    /// [Editor(typeof(ResourcePathEditor), typeof(UITypeEditor))]
 25    /// [TypeConverter(typeof(OnlySelectableTypeConverter))]
 26    /// public string ResourcePath { get; set; }
 27    /// </code>
 28    /// </example>
 29    /// <seealso cref="Attribute"/>
 30    /// <seealso cref="ResourcePathEditor"/>
 31    /// <seealso cref="OnlySelectableTypeConverter"/>
 32    [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
 9233    public class AllowBlankAttribute(bool allow = true, bool includeItem = false, string resourceItem = "") : Attribute
 34    {
 35#else
 36    /// <summary>
 37    /// Specifies whether a blank (empty) value is allowed for a property, typically used in dropdown editors.
 38    /// </summary>
 39    /// <remarks>
 40    /// This attribute is used in conjunction with editors like <see cref="ResourcePathEditor"/> and converters
 41    /// like <see cref="OnlySelectableTypeConverter"/> to optionally include a blank entry in the list of selectable val
 42    /// </remarks>
 43    /// <example>
 44    /// <code language="csharp">
 45    /// [AllowBlank(includeItem: true, resourceItem: "Blank_DisplayText")]
 46    /// [Editor(typeof(ResourcePathEditor), typeof(UITypeEditor))]
 47    /// [TypeConverter(typeof(OnlySelectableTypeConverter))]
 48    /// public string ResourcePath { get; set; }
 49    /// </code>
 50    /// </example>
 51    /// <seealso cref="Attribute"/>
 52    /// <seealso cref="ResourcePathEditor"/>
 53    /// <seealso cref="OnlySelectableTypeConverter"/>
 54    [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
 55    public class AllowBlankAttribute : Attribute
 56    {
 57        /// <summary>
 58        /// Initializes a new instance of the <see cref="AllowBlankAttribute" /> class.
 59        /// </summary>
 60        /// <param name="allow">if set to <c>true</c> allow blank values in the property.</param>
 61        /// <param name="includeItem">if set to <c>true</c> include item in the dropdown to indicate blank.</param>
 62        /// <param name="resourceItem">The resource item to use for displaying the blank item (Leaves it empty when this
 1663        public AllowBlankAttribute(bool allow = true, bool includeItem = false, string resourceItem = "")
 864        {
 1665            Allow = allow;
 1666            IncludeItem = includeItem;
 1667            ResourceItem = resourceItem;
 1668        }
 69#endif
 70
 71        /// <summary>
 72        /// Gets a value indicating whether this <see cref="AllowBlankAttribute"/> is allowing blank values.
 73        /// </summary>
 74        /// <value>
 75        ///   <c>true</c> if allow blank values; otherwise, <c>false</c>.
 76        /// </value>
 77        public bool Allow
 78        {
 8079            get;
 80#if NET8_0_OR_GREATER
 9281        } = allow;
 82#else
 83        }
 84#endif
 85        /// <summary>
 86        /// Gets a value indicating whether to include item an item in the dropdown to indicate blank.
 87        /// </summary>
 88        /// <value>
 89        ///   <c>true</c> if including an item in the dropdown to indicate blank; otherwise, <c>false</c>.
 90        /// </value>
 91        public bool IncludeItem
 92        {
 9293            get;
 94#if NET8_0_OR_GREATER
 9295        } = includeItem;
 96#else
 97        }
 98#endif
 99
 100        /// <summary>
 101        /// Gets the resource item to use for displaying the blank item (Leaves it empty when this is not provided).
 102        /// </summary>
 103        /// <value>
 104        /// The resource item to use for displaying the blank item (Leaves it empty when this is not provided).
 105        /// </value>
 106        public string ResourceItem
 107        {
 60108            get;
 109#if NET8_0_OR_GREATER
 92110        } = resourceItem;
 111#else
 112        }
 113#endif
 114
 115        /// <summary>
 116        /// Determines whether blank is allowed in the specified context.
 117        /// </summary>
 118        /// <param name="context">The context.</param>
 119        /// <returns>
 120        ///   <c>true</c> if blank is allowed in the specified context; otherwise, <c>false</c>.
 121        /// </returns>
 122        public static bool IsBlankAllowed(ITypeDescriptorContext context)
 48123        {
 56124            var prop = Get(context);
 56125            return prop != null && prop.Allow;
 48126        }
 127
 128        /// <summary>
 129        /// Gets the blank label.
 130        /// </summary>
 131        /// <param name="context">The context.</param>
 132        /// <returns></returns>
 133        public static string GetBlankLabel(
 134            ITypeDescriptorContext context)
 56135        {
 64136            if (context?.PropertyDescriptor == null || context.Instance == null)
 20137                return string.Empty;
 138
 139            // Check for AllowBlankAttribute on the property
 60140            var allowBlankAttr = Get(context);
 60141            if (allowBlankAttr == null || !allowBlankAttr.Allow)
 20142                return string.Empty;
 143
 144            // Determine the baseName from the class's ResourcePathAttribute
 56145            var resourcePathAttr = context.Instance.GetType()
 56146                .GetCustomAttributes(typeof(ResourcePathAttribute), true);
 147
 56148            string baseName = null;
 56149            if (resourcePathAttr.Length > 0 && resourcePathAttr[0] is ResourcePathAttribute rpa)
 36150                baseName = rpa.ResourcePath;
 151
 152            // If we want to include an item in the list and have a resource item name, use it
 56153            if (allowBlankAttr.IncludeItem && !string.IsNullOrEmpty(allowBlankAttr.ResourceItem))
 40154            {
 155                try
 40156                {
 48157                    if (!string.IsNullOrEmpty(baseName))
 20158                    {
 28159                        var rootNamespace = context.Instance.GetType().Namespace.Split('.')[0];
 28160                        var fullResourcePath = $"{rootNamespace}.{baseName}";
 161
 28162                        var manager = new ComponentResourceManager(context.Instance.GetType().Assembly.GetType(fullResou
 24163                        var localized = manager.GetString(allowBlankAttr.ResourceItem, CultureInfo.CurrentCulture);
 24164                        if (!string.IsNullOrEmpty(localized))
 20165                            return localized;
 12166                    }
 40167                }
 20168                catch
 12169                {
 170                    // Fall through to default
 20171                }
 36172            }
 173
 174            // Default to "(none)" if no localized string is found or we aren't including the label
 52175            return allowBlankAttr.IncludeItem ? "(none)" : string.Empty;
 64176        }
 177
 178        /// <summary>
 179        /// Gets the specified context.
 180        /// </summary>
 181        /// <param name="context">The context.</param>
 182        /// <returns></returns>
 183        public static AllowBlankAttribute Get(ITypeDescriptorContext context) =>
 112184            context == null || context.Instance == null || context.PropertyDescriptor == null
 112185                ? null
 112186                : Support.Support.GetFirstCustomAttribute<AllowBlankAttribute>(
 112187                    Support.Support.GetPropertyInfo(context));
 188
 189        /// <summary>
 190        /// Converts to string.
 191        /// </summary>
 192        /// <returns>
 193        /// A <see cref="string" /> that represents this instance.
 194        /// </returns>
 195        public override string ToString() =>
 20196            $"AllowBlank: {Allow}, IncludeItem: {IncludeItem}, ResourceItem: '{ResourceItem}'";
 197    }
 198}