Search code examples
c#winformsdesigner

Auto-generate the code-behind name of designer collection items


I have a custom control with a public collection marked as DesignerSerializationVisibility.Content.

When I add items to the collection using the designer, it adds them to the designer file and assigns all desired values but it gives each element of the collection a generic name, such as MyClass1, MyClass2, etc. I want the "Name" property of each item to become the code name of the item so that I can then access the item by its name in code.

This is the functionality of how a ContextMenuStrip and ToolStrip works. In those cases, the Name property shows up as (Name) in the property grid.

Is there an attribute or something I can use to gain this functionality? Or do I have to write a whole custom designer dialog? If so, what's an example of the simplest way I could go about achieving this?


Solution

  • You can try inheriting from Component to get that feature.

    In this example, I created a class called PanelItem, which will be the class used in my collection by my own Panel class. I added DesignTimeVisible(false) so that it doesn't populate the component tray in the designer.

    Also, I added a Name property that is hidden from the designer but can be used in code. It seemed to work in my tests:

    [DesignTimeVisible(false)]
    public class PanelItem : Component  {
    
      [DefaultValue(typeof(string), "")]
      public string PanelText { get; set; }
    
      private string name = string.Empty;
    
      [Browsable(false)]
      [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
      public string Name {
        get {
          if (base.Site != null) {
            name = base.Site.Name;
          }
          return name;
        }
        set {
          name = value;
        }
      }
    }
    

    Then my custom panel control:

    public class MyPanel : Panel {
      private List<PanelItem> panelItems = new List<PanelItem>();
    
      [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
      public List<PanelItem> PanelItems {
        get { return panelItems; }
      }
    }
    

    Resulted in:

    enter image description here