Problem with designtime support for controls with collections

Hi guys,

I wanr to write a Control, which allows me to add Columns at designtime. Similar to the ListView Control. I have implemented 3 classes:

VTraceColumn   (has Informations about the columns)
VTraceColumnCollection  (this is the collection class)
VTrace       (my control, which should show the columns)


VTraceColumn   is inherited from Component and has Informations about the Columns (Caption, witdth etc.). VTraceColumnCollection  ist inherited from CollectionBase and overrides all the Methods and works fine so far. VTrace is inherited from Control. When I add the columns manually to the collection everything works fine. But I got problems at designtime using the propertygrid:

1. I use the CollectionEditor, to edit the collection via the propertygrid. Adding columns is no problem, they get actualized at the moment. But when I remove them, nothing happens until I close the CollectionEditor.

2.  When I delete the instance of VTrace on my Form the instances of the VTraceColumns remain. Why



Her is the code for VTraceColumnCollection and VTraceColum:


    [
    DesignTimeVisible(false),
    System.ComponentModel.ToolboxItemAttribute(false)
    ]
    public class VTraceColumn : Component
    {
        private int _Width;
        
        public VTraceColumn()
        {
            Width = 100;
        }

        public int Width
        {
            get
            {
                return _Width;
            }
            set
            {
                _Width = value;
            }
        }
   }




    public class VTraceColumnCollection : CollectionBase
    {
        private VTrace m_Owner;

        public VTraceColumnCollection(VTrace owner)
        {
            m_Owner = owner;
        }

        public /* IList */ bool IsFixedSize
        {
            get
            {
                return false;
            }
        }

        public /* IList */ bool IsReadOnly
        {
            get
            {
                return false;
            }
        }

        public /* IList */ VTraceColumn this[int index]
        {
            set
            {
                InnerList[index] = value;
                m_Owner.Invalidate();
            }
            get
            {
                return (VTraceColumn) InnerList[index];
            }
        } 

        public int /* IList */ Add(VTraceColumn column)
        {
            int returnValue = InnerList.Add(column);
            m_Owner.Invalidate();
            return returnValue;
        }

        /*public void Clear() not needed, because implemented by CollectionBase*/
        /*instead working on OnClear and OnClearComplete*/ 
        protected override void OnClear()
        {
            base.OnClear ();
        }
        protected override void OnClearComplete()
        {
            base.OnClearComplete ();
            m_Owner.Invalidate();
        }

        public /* IList */ bool Contains(VTraceColumn column)
        {
            return InnerList.Contains(column);
        }

        public /* IList */ int IndexOf(VTraceColumn column)
        {
            return InnerList.IndexOf(column);
        }

        public /* IList */ void Insert(int index, VTraceColumn column)
        {
            InnerList.Insert(index, column);
            m_Owner.Invalidate();
        }

        public /* IList */ void Remove(VTraceColumn column)
        {
            InnerList.Remove(column);
            m_Owner.Invalidate();
        }

        /*public void RemoveAt() not needed, because implemented by CollectionBase*/
        /*instead working on OnRemove and OnRemoveComplete*/ 
        protected override void OnRemove(int index, object value)
        {
            base.OnRemove (index, value);
        }
        protected override void OnRemoveComplete(int index, object value)
        {
            base.OnRemoveComplete (index, value);
            m_Owner.Invalidate();
        }

        /*Count not needed, because implemented by CollectionBase*/

        public /* ICollection */ bool IsSynchronized
        {
            get
            {
                return false;
            }
        }

        public /* ICollection */ object SyncRoot
        {
            get
            {
                return this;
            }
        }

        public void CopyTo(Array array, int index)
        {
            InnerList.CopyTo(array, index);
        }
    }










The VTraceColumsCollection property of the control has the following signature:

[
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
        EditorAttribute("System.ComponentModel.Design.CollectionEditor",  "System.Drawing.Design.UITypeEditor")
        ]
        public VTraceColumnCollection Columns
        {
            get
            {
                return _Columns;
            }
        }






Answer this question

Problem with designtime support for controls with collections

  • Julianín

    I think you need a designer to synchronize your changes and instruct it what to do on changes on your collection.  I am not an expert when it comes to designer, all I can provide you is a link to a good resource which I have read last week.

    try this <a href="http://www.divil.co.uk/net/articles/designers/collectioncontrols.asp">http://www.divil.co.uk/net/articles/designers/collectioncontrols.asp</a>

  • talk2Sushant

    Ok, what exactly are you trying to do   Get away from the technical side of coding (designer attributes) and tell us what is the function of your UserControl.

    Let's say you have a UserControl with a Panel Control as main component.  Inside the panel Control, you want to have a number of Label Controls.  I'm assuming that they aren't fixed, reason why you need to expose their properties and have them editable.  Let's start this way...

    About the grid, the TableStyles and ColumnStyles are just components and not controls.  They don't have appearances at design time and you can set them from the collection properties of the grid but all it does is to configure the grid then serialize the configuration as part of the grid in InitializeComponent.  At runtime, there and then, they are used.

    Try to look at this link for the meantime:
    http://www.divil.co.uk/net/articles/designers/collectioncontrols.asp

  • Norman Diamond

    I have a problem with a collection of controls on a custom control in the designer.  It appears you have developed something that may help with my problem.

    I am interested in someone providing a sample that has a panel on a user control that contains a collection of controls available at design time. To put it simply I would like the following.

    1. a user control
    2. a panel control
    3. a collection of, let's say, label controls that are accessible at design time that are contained on the panel

    I understand the method to add a collection, or any control, to the properties window is <DesignerSerializationVisibility(DesignerSerializat ionVisibility.Content)>. What I don't understand is 1. How to create the collection of controls and where to place the <DesignerSerializationVisibility(DesignerSerializat ionVisibility.Content)>. 2. How to place the controls on the Panel at design time.

    BTW, I haven't found this simple example on any of the forums. I think Microsoft should provide a decent example of this.
     
    I need a user control containing a panel with a collection of controls where the user control has the collection exposed in it's property window when it is dropped on a form. This will be much like the grid control, which has a columns property in it's property window. When the user clicks on the ellipse '...' an editor pops up where you can add and remove columns and set their properties.
     
    OK, I was able to build the collection without help. Is there anyone that would care to tackle this problem  The collections of buttons, labels, and textboxes are now exposed in the property window for the Usercontrol. The problem is, when I add a control to the collection it is not apperant where it is placed. It shows up in code for the form in the Windows Generated Code section, but I can't locate it on the form or the Usercontrol. 

  • smcintyr11

    Are you using the IComponentChangeService for the designer of your control
  • Mario Queiroz

    I didn't write a designer, yet.
    Should I do this
    I think the ListView Control doesn't use a specialized designer, too. But I'm not sure. This functionality should com from the CollectionEditor.

  • mmarsh

    No sure if you already got an answer to this but....

    I'm having a similar problem.  I think I've found the solution: Don't bother with OnRemoveComplete.  I have a feeling that the CollectionEditor never actually removes the items from the collection.  Rather, I'm guessing, it clears the whole collection when you hit OK, then it adds the items you haven't removed back in.

    This means that you need to override OnClearComplete and OnInsertComplete, but not OnRemoveComplete.  You might as well override all three just in case someone decides to call a remove method on your collection, though.

  • Problem with designtime support for controls with collections