< Summary - PropertyGridHelpers Code Coverage

Information
Class: PropertyGridHelpers.UIEditors.DropDownVisualizer<TControl>
Assembly: PropertyGridHelpers
File(s): c:\agent\_work\9\s\Code\PropertyGridHelpers\UIEditors\DropDownVisualizer.cs
Tag: PropertyGridHelpers Build_2025.7.15.1_#485
Line coverage
100%
Covered lines: 35
Uncovered lines: 0
Coverable lines: 35
Total lines: 145
Line coverage: 100%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100

Metrics

File(s)

c:\agent\_work\9\s\Code\PropertyGridHelpers\UIEditors\DropDownVisualizer.cs

#LineLine coverage
 1using PropertyGridHelpers.Support;
 2using System;
 3using System.ComponentModel;
 4using System.Diagnostics;
 5using System.Drawing.Design;
 6using System.Globalization;
 7using System.Windows.Forms;
 8using System.Windows.Forms.Design;
 9
 10namespace PropertyGridHelpers.UIEditors
 11{
 12    /// <summary>
 13    /// A reusable drop-down <see cref="UITypeEditor"/> that hosts a custom Windows Forms
 14    /// control to edit a property value.
 15    /// </summary>
 16    /// <typeparam name="TControl">
 17    /// The type of the Windows Forms control to be shown in the dropdown.
 18    /// Must implement <see cref="IDropDownEditorControl"/>.
 19    /// </typeparam>
 20    /// <remarks>
 21    /// This class simplifies building custom UI editors for use in <see cref="PropertyGrid"/>
 22    /// by wrapping a control that supports editing a specific data type. The
 23    /// dropdown closes automatically when the control raises the
 24    /// <see cref="IDropDownEditorControl.ValueCommitted"/> event.
 25    ///
 26    /// To use it, decorate your property with:
 27    /// <code>
 28    /// [Editor(typeof(DropDownVisualizer&lt;MyControl&gt;), typeof(UITypeEditor))]
 29    /// public MyValueType MyProperty { get; set; }
 30    /// </code>
 31    ///
 32    /// The provided control type must:
 33    /// - Be a subclass of <see cref="Control"/>
 34    /// - Implement <see cref="IDropDownEditorControl"/>
 35    /// - Have a parameterless constructor
 36    /// </remarks>
 37    /// <example>
 38    /// A simple calculator bound to a decimal property:
 39    /// <code>
 40    /// [Editor(typeof(DropDownVisualizer&lt;CalculatorControl&gt;), typeof(UITypeEditor))]
 41    /// public decimal Total { get; set; }
 42    /// </code>
 43    /// </example>
 44    /// <seealso cref="UITypeEditor" />
 45    /// <seealso cref="IDisposable" />
 46    public class DropDownVisualizer<TControl> : UITypeEditor, IDisposable
 47        where TControl : Control, IDropDownEditorControl, new()
 48    {
 49        private bool disposedValue;
 50
 51        /// <summary>
 52        /// The instance of the drop-down control currently used by the
 53        /// editor. This can be configured before editing starts (e.g.,
 54        /// setting styles, converters, or event handlers).
 55        /// </summary>
 56        /// <value>The drop-down control instance.</value>
 1657        public TControl DropDownControl { get; private set; } = new TControl();
 58
 59        /// <inheritdoc/>
 60        public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) =>
 1661            UITypeEditorEditStyle.DropDown;
 62
 63        /// <summary>
 64        /// Displays the editor control in a dropdown and returns the updated
 65        /// value after editing completes.
 66        /// </summary>
 67        /// <param name="context">
 68        /// Provides context information about the design-time environment.
 69        /// </param>
 70        /// <param name="provider">
 71        /// A service provider that can provide an <see cref="IWindowsFormsEditorService"/>.
 72        /// </param>
 73        /// <param name="value">
 74        /// The current value of the property being edited.
 75        /// </param>
 76        /// <returns>
 77        /// The edited value as returned by the control, or the original value
 78        /// if editing is canceled or fails.
 79        /// </returns>
 80        public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
 881        {
 1682            if (context != null &&
 1683                context.Instance != null &&
 1684                provider != null &&
 1685                context.PropertyDescriptor != null)
 886            {
 1687                if (provider.GetService(typeof(IWindowsFormsEditorService)) is IWindowsFormsEditorService edSvc)
 888                {
 1689                    DropDownControl.Context = context;
 1690                    DropDownControl.Culture = CultureInfo.CurrentCulture;
 1691                    DropDownControl.Value = value;
 92
 93                    void OnValueCommitted(object s, EventArgs e) => edSvc.CloseDropDown();
 94
 1695                    DropDownControl.ValueCommitted += OnValueCommitted;
 96
 1697                    edSvc.DropDownControl(DropDownControl);
 98
 1699                    DropDownControl.ValueCommitted -= OnValueCommitted;
 100
 16101                    return DropDownControl.Value;
 102                }
 8103            }
 104
 8105            Debug.WriteLine("DropDownVisualizer failed due to missing context or services.");
 16106            return null;
 8107        }
 108
 109        /// <summary>
 110        /// Releases unmanaged and - optionally - managed resources.
 111        /// </summary>
 112        /// <param name="disposing">
 113        /// <c>true</c> to release both managed and unmanaged resources;
 114        /// <c>false</c> to release only unmanaged resources.
 115        /// </param>
 116        /// <remarks>
 117        /// This editor implements <see cref="IDisposable"/> and ensures the
 118        /// hosted control is disposed after use.
 119        /// </remarks>
 120        protected virtual void Dispose(bool disposing)
 8121        {
 16122            if (!disposedValue)
 8123            {
 16124                if (disposing)
 8125                {
 16126                    DropDownControl.Dispose();
 8127                }
 128
 129                // TODO: free unmanaged resources (unmanaged objects) and override finalizer
 130                // TODO: set large fields to null
 16131                disposedValue = true;
 8132            }
 16133        }
 134
 135        /// <summary>
 136        /// Releases unmanaged and - optionally - managed resources.
 137        /// </summary>
 138        public void Dispose()
 8139        {
 140            // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
 16141            Dispose(disposing: true);
 16142            GC.SuppressFinalize(this);
 16143        }
 144    }
 145}