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:


Migrating from .Net 6.0 to .Net Framework 4.8.1 solved my problems.
How designer works:
When designer is open,
InitializeComponentcontent is compiled into assembly in fly, on which the interactive designer preview is built. It is worth noticing thatProperties Windowis a part of Visual Studio.Short Explanation:
Further Reading: