Custom CollectionEditor not showing in design time, default one is launching

96 views Asked by At

I'm working on C# app in Winforms. I created custom CollectionEditor for my Custom Control. It is working perfectly at runtime with PropertyGrid, but at design time default CollectionEditor is launching.

At design time I want to add MainTabPage (customized TabPage) to MainTabControl (customized TabControl), so I customized my CollectionEditor. But regular TabControl editor is launching, not my custom one.

MainTabControl:

public partial class MainTabControl : TabControl
{
    private readonly int mouseAreaTriggerOffset = 3;
    private int standardOffset;
    private Size closeButtonSize;
    private Size textSize;

    [EditorAttribute(typeof(MainTabPageCollectionEditor), typeof(UITypeEditor))]
    [Browsable(true)]
    public new TabPageCollection TabPages
    {
        get
        {
            return base.TabPages;
        }
    }

    public MainTabControl()
    {
        InitializeComponent();

        this.DrawMode = TabDrawMode.OwnerDrawFixed;
    }

    protected override void OnDrawItem(DrawItemEventArgs e)
    {
        standardOffset = (int)(this.ItemSize.Width * 0.05);

        for (int i = 0; i < this.TabPages.Count; i++)
        {
            // Image
            //Image image = this.ImageList.Images["AddAccount.png"];
            Size imageSize = new Size(e.Bounds.Height / 2, e.Bounds.Height / 2);
            //e.Graphics.DrawImage(image, new Rectangle(e.Bounds.Left + standardOffset, e.Bounds.Top + (e.Bounds.Height - imageSize.Height) / 2, imageSize.Width, imageSize.Height));

            // Text
            textSize = TextRenderer.MeasureText(this.TabPages[e.Index].Text, e.Font);
            e.Graphics.DrawString(this.TabPages[e.Index].Text, e.Font, Brushes.Black,
                e.Bounds.Left + 2 * standardOffset + imageSize.Width,
                e.Bounds.Top + (e.Bounds.Height - textSize.Height) / 2);

            // Close button
            closeButtonSize = TextRenderer.MeasureText("x", e.Font);
            e.Graphics.DrawString("x", e.Font, Brushes.Red,
                e.Bounds.Right - closeButtonSize.Width / 2 - standardOffset,
                e.Bounds.Top + (e.Bounds.Height - closeButtonSize.Height) / 2);

            // Line
            Pen pen = new Pen(Brushes.MediumBlue, 3);
            e.Graphics.DrawLine(pen, e.Bounds.Left + standardOffset, 4, e.Bounds.Right - standardOffset, 4);
        }

        base.OnDrawItem(e);
    }

    protected override void OnMouseDown(MouseEventArgs e)
    {
        for (int i = 0; i < this.TabPages.Count; i++)
        {
            // ...
        }

        base.OnMouseDown(e);
    }

    protected override void OnMouseMove(MouseEventArgs e)
    {
        for (int i = 0; i < this.TabPages.Count; i++)
        {
            Rectangle bounds = this.GetTabRect(i);
            Rectangle closureBounds = new Rectangle(
                bounds.Right - closeButtonSize.Width / 2 - standardOffset - mouseAreaTriggerOffset,
                bounds.Top + (bounds.Height - closeButtonSize.Height) / 2 - mouseAreaTriggerOffset,
                closeButtonSize.Width + 2 * mouseAreaTriggerOffset,
                closeButtonSize.Height + 2 * mouseAreaTriggerOffset);

            if (closureBounds.Contains(e.Location))
            {
                // ...
            }
        }

        base.OnMouseMove(e);
    }
}

MainTabPage:

public partial class MainTabPage : TabPage
{
    private bool isClosable;

    [Browsable(true)]
    [Description("Indicates whether the tab could be closed")]
    [Category("Behavior")]
    public bool IsClosable { get; set; }

    [Browsable(true)]
    [Description("Indicates whether the tab has the icon")]
    [Category("Appearance")]
    public bool IsIcon { get; set; }

    [Browsable(true)]
    [Description("Indicates whether the tab has upper line")]
    [Category("Appearance")]
    public bool IsUpperLine { get; set; }

    public MainTabPage()
    {
        InitializeComponent();
    }

    public MainTabPage(string text) : this()
    {
        Text = text;
    }
}

MainTabPageCollectionEditor:

public class MainTabPageCollectionEditor : CollectionEditor
{
    public MainTabPageCollectionEditor(Type type)
        : base(type)
    {  }

    protected override object CreateInstance(Type itemType)
    {
        object instance = base.CreateInstance(itemType);

        MainTabPage mainTabPage = instance as MainTabPage;
        mainTabPage.UseVisualStyleBackColor = true;

        return mainTabPage;
    }

    protected override Type CreateCollectionItemType()
    {
        return typeof(MainTabPage);
    }
}

Images:

During Runtime: MainTabPageCollectionEditor at Runtime

During Design time: Default CollectionEditor at Design time

1

There are 1 answers

0
NeverDoomedEnough On

Migrating from .Net 6.0 to .Net Framework 4.8.1 solved my problems.

Here's what I've learned:

How designer works:
When designer is open, InitializeComponent content is compiled into assembly in fly, on which the interactive designer preview is built. It is worth noticing that Properties Window is a part of Visual Studio.

Short Explanation:

  • In .Net Framework project, the designer runs in the same process as Visual Studio, so things are straightforward.
  • In .Net (Core) project, the designer runs in another process, because .Net Framework (in which Visual Studio runs) and .Net Core can't run within one process. There are some comlicated ways to overcome it (see links below), but I resign from trying.

Further Reading: