0

Follow-up from: Windows Forms designer, ObservableCollection<Control> and TableLayoutPanel, controls added at design-time don't show anymore when project is run

I'm writing a custom control which inherits from TableLayoutPanel and has a custom designer. The designer has a Collection of Labels which is exposed to Visual Studio Designer's properties window.

This is what I have so far:

using Microsoft.DotNet.DesignTools.Designers;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace TestTableLayoutPanel
{
    [Designer(typeof(TlpLabelsDesigner))]
    public partial class TlpLabels : TableLayoutPanel
    {
        public TlpLabels()
        {
            InitializeComponent();
        }
    }




    public class TlpLabelsDesigner : ControlDesigner
    {
        public override void Initialize(IComponent component)
        {
            base.Initialize(component);
            labels.CollectionChanged += OnLabelsChanged;
        }

        
        private readonly ObservableCollection<Label> labels = new ObservableCollection<Label>();
        public ObservableCollection<Label> Labels { get { return labels; } }

        private void OnLabelsChanged(object? sender, EventArgs e)
        {
            TableLayoutPanel tlp = (TableLayoutPanel)Control;

            tlp.RowStyles.Clear();
            tlp.RowCount = Labels.Count;

            for(int i = 0; i < tlp.RowCount; i++)
                tlp.RowStyles.Add(new RowStyle(SizeType.Percent, 100.0F / tlp.RowCount));

            for (int j = 0; j < tlp.RowCount; j++)
            {
                labels[j].Anchor = AnchorStyles.None;
                labels[j].TextAlign = ContentAlignment.MiddleCenter;
                tlp.Controls.Add(labels[j]);
            }
        }



        private readonly string[] RemovedProperties = new string[]
        {
            "Cell", "CellBorderStyle", "Column", "ColumnCount", "ColumnSpan", "GrowStyle", "Row", "RowCount", "RowSpan"
        };

        protected override void PreFilterProperties(IDictionary properties)
        {
            foreach (string prop in RemovedProperties)
                properties.Remove(prop);

            string desc = "Auflistung aller Labels, die im TableLayoutPanel eingeordnet und angezeigt werden.";

            PropertyDescriptor pd = TypeDescriptor.CreateProperty(typeof(TlpLabelsDesigner), "Labels", typeof(ObservableCollection<Label>),
                                                                  new Attribute[] { new DesignOnlyAttribute(false),
                                                                                    new BrowsableAttribute(true),
                                                                                    new CategoryAttribute("Layout"),
                                                                                    new DescriptionAttribute(desc)});
            properties.Add("Labels", pd);

            base.PreFilterProperties(properties);
        }
    }
}

The problems I have with it:

  1. When I open the collection editor and add Labels, the code to initialize them is put into Form1.Designer.cs, instead of TlpLabels.Designer.cs
  2. When I run and close the application and open the collection editor again, the list is empty. Just the list though; initialization code in Form1.Designer.cs is still there, and the labels are still shown in the form.
Flipps
  • 11
  • 5
  • You collection of Labels needs its own Designer, derived from `CollectionEditor`, so you have and active `IDesignerHost` service that handles creation / destruction of Components (on the Host's site, not the Client's) and an `IComponentChangeService`. If you thought that using an ObservableCollection could replace the latter, you're out of luck – Jimi May 26 '23 at 13:17
  • I have worked through the example code snippets by MS. `CollectionEditor`: Creates/destroys the labels, provides a form in which I can handle the labels; `IComponentChangeService`: I have to use its events to put the newly created labels into the TableLayoutPanel. `IDesignerHost` starts the CollectionEditor, when implemented. Is this correct? – Flipps Jun 02 '23 at 08:26

0 Answers0