File: System\Windows\Forms\Design\DataGridViewColumnTypeEditor.Picker.cs
Web Access
Project: src\src\System.Windows.Forms.Design\src\System.Windows.Forms.Design.csproj (System.Windows.Forms.Design)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Collections;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
 
namespace System.Windows.Forms.Design;
 
[ToolboxItem(false)]
[DesignTimeVisible(false)]
internal partial class DataGridViewColumnTypePicker : ContainerControl
{
    private readonly ListBox _typesListBox;
    private Type? _selectedType;
 
    // The current editor service that we need to close the drop down.
    private IWindowsFormsEditorService? _windowsFormsEditorService;
    private static readonly Type s_dataGridViewColumnType = typeof(DataGridViewColumn);
 
    private const int MinimumHeight = 90;
    private const int MinimumWidth = 100;
 
    public DataGridViewColumnTypePicker()
    {
        _typesListBox = new();
        Size = _typesListBox.Size;
        _typesListBox.Dock = DockStyle.Fill;
        _typesListBox.Sorted = true;
        _typesListBox.HorizontalScrollbar = true;
        _typesListBox.SelectedIndexChanged += typesListBox_SelectedIndexChanged;
        Controls.Add(_typesListBox);
        BackColor = SystemColors.Control;
        ActiveControl = _typesListBox;
    }
 
    public Type? SelectedType => _selectedType;
 
    private int PreferredWidth
    {
        get
        {
            int width = 0;
            using Graphics g = _typesListBox.CreateGraphics();
 
            for (int i = 0; i < _typesListBox.Items.Count; i++)
            {
                ListBoxItem item = (ListBoxItem)_typesListBox.Items[i];
                width = Math.Max(width, Size.Ceiling(g.MeasureString(item.ToString(), _typesListBox.Font)).Width);
            }
 
            return width;
        }
    }
 
    private void CloseDropDown() => _windowsFormsEditorService?.CloseDropDown();
 
    protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)
    {
        if ((BoundsSpecified.Width & specified) == BoundsSpecified.Width)
        {
            width = Math.Max(width, MinimumWidth);
        }
 
        if ((BoundsSpecified.Height & specified) == BoundsSpecified.Height)
        {
            height = Math.Max(height, MinimumHeight);
        }
 
        base.SetBoundsCore(x, y, width, height, specified);
    }
 
    /// <devdoc>
    ///  Setup the picker, and fill it with type information
    /// </devdoc>
    public void Start(IWindowsFormsEditorService edSvc, ITypeDiscoveryService discoveryService, Type defaultType)
    {
        _windowsFormsEditorService = edSvc;
 
        _typesListBox.Items.Clear();
 
        ICollection columnTypes = DesignerUtils.FilterGenericTypes(discoveryService.GetTypes(s_dataGridViewColumnType, excludeGlobalTypes: false));
 
        foreach (Type t in columnTypes)
        {
            if (t == s_dataGridViewColumnType)
            {
                continue;
            }
 
            if (t.IsAbstract)
            {
                continue;
            }
 
            if (!t.IsPublic && !t.IsNestedPublic)
            {
                continue;
            }
 
            DataGridViewColumnDesignTimeVisibleAttribute? attr = TypeDescriptor.GetAttributes(t)[typeof(DataGridViewColumnDesignTimeVisibleAttribute)] as DataGridViewColumnDesignTimeVisibleAttribute;
            if (attr is not null && !attr.Visible)
            {
                continue;
            }
 
            _typesListBox.Items.Add(new ListBoxItem(t));
        }
 
        _typesListBox.SelectedIndex = TypeToSelectedIndex(defaultType);
 
        _selectedType = null;
 
        // Set our default width.
        Width = Math.Max(Width, PreferredWidth + (SystemInformation.VerticalScrollBarWidth * 2));
    }
 
    private void typesListBox_SelectedIndexChanged(object? sender, EventArgs e)
    {
        _selectedType = _typesListBox.SelectedItem is ListBoxItem selectedItem ? selectedItem.ColumnType : null;
        _windowsFormsEditorService?.CloseDropDown();
    }
 
    private int TypeToSelectedIndex(Type type)
    {
        for (int i = 0; i < _typesListBox.Items.Count; i++)
        {
            if (type == ((ListBoxItem)_typesListBox.Items[i]).ColumnType)
            {
                return i;
            }
        }
 
        Debug.Assert(false, "we should have found a type by now");
 
        return -1;
    }
}