Bringing controls out from design-time

I'm using standard DesignSurface for control design in my custom editor and I'm trying to serialize designed controls with my custom serializator that simply recursively parses the root component and emits custom serialization data for each and every component.

The problem is that some components contain objects that were created by their designers. For example, the MenuStrip in its Items collection has a DesignerToolStripMenuHost object that is used for designing menu items.

My serialization process cannot generically differentiate these design-time objects from real ones. The solution could be to remove the components from design-time. This could be done using IDesignerHost.Remove service but doing so throws exceptions (it looks that the order of removing components is important).

Is there a simple (or any other) way to bring components out from design-time



Answer this question

Bringing controls out from design-time

  • Attila Hajdrik

    Can you post code you use for iteration and remove

  • Jason Sa

    Hi!

     

    When you remove items from collection - alive enumerators throw exceptions. To escape this just enumerate collection from end to the beginning and remove last items.

    Such method will not require memory for copy of the original list and it works faster (no need to query for IEnumerable/IEnumerator interfaces).

    In VS2005 use "forr" code snippet to create necessary reverse for().

    Here is sample:

     

    IList list;

    ...

    for (int i = list.Count - 1; i >= 0; i--)

    {

    list.RemoveAt(i);

    }



  • charafeddine

    Maybe this procedure helps to you (the code is placed into your host form):

     

    /// <summary>
    /// Remove the components for an specific type
    /// </summary>
    /// <param name="compcollectiontoremove">The IContainer with the components to remove</param>

    public void RemoveComponents()

    {

    if (this.host != null)
    {

    IContainer compcollectiontoremove = this.host.Container;
    if (compcollectiontoremove != null)
    {

    ArrayList m_tempoCollection = new ArrayList(compcollectiontoremove.Components);

    foreach (IComponent m_component in m_tempoCollection)

    {

    if (m_component.GetType().Assembly.GetName().Name == "Your.Type.To.Remove")

    {

    //This code remove the componet from designer host
    this.host.DestroyComponent(m_component);

    }

    }

    }

    }

    }


  • Tim Vasil

    Hello!

    If you are using a for...each statement to access each component in your components collection and try of remove an component, yes... one exception is fired. The solution is to clone your component colecction, then you will to use this cloned collection (in your for...each bucle) and locate the component that you don't want serialize and remove it from the original collection (the serializable). You must implement the ISerializable interface to define the elements to serialize or not serialize. Maybe you need to use a CodeDom serializer.

    Regards


  • RyanJ

    Well there's not much to post but here it is:

    for (int i = _host.Container.Components.Count - 1; i >= 0; i--)

    {

    if (_host.Container.ComponentsIdea != _host.RootComponent)

    _host.Container.Remove(_host.Container.ComponentsIdea);

    }

    I'm removing all the designed components except the root component.


  • udaijeet

    Thank you for your help, but iteration wasn't the problem, I iterated backward in the first place.

    During the iteration process (when the iterator was set on MenuStrip component) the null reference exc. is fired with the following stack trace:

    at System.Windows.Forms.Design.ToolStripDesigner.GetControlGlyph(GlyphSelectionType selectionType)

    at System.Windows.Forms.Design.Behavior.SelectionManager.AddControlGlyphs(Control c, GlyphSelectionType selType)

    at System.Windows.Forms.Design.Behavior.SelectionManager.AddAllControlGlyphs(Control parent, ArrayList selComps, Object primarySelection)

    at System.Windows.Forms.Design.Behavior.SelectionManager.AddAllControlGlyphs(Control parent, ArrayList selComps, Object primarySelection)

    at System.Windows.Forms.Design.Behavior.SelectionManager.OnSelectionChanged(Object sender, EventArgs e)

    at System.Windows.Forms.Design.Behavior.SelectionManager.Refresh()

    at System.Windows.Forms.Design.Behavior.SelectionManager.OnComponentChanged(Object source, ComponentChangedEventArgs ce)

    at System.ComponentModel.Design.ComponentChangedEventHandler.Invoke(Object sender, ComponentChangedEventArgs e)

    at System.ComponentModel.Design.DesignerHost.System.ComponentModel.Design.IComponentChangeService.OnComponentChanged(Object component, MemberDescriptor member, Object oldValue, Object newValue)

    at System.Windows.Forms.Design.ParentControlDesigner.OnComponentRemoved(Object sender, ComponentEventArgs e)

    at System.ComponentModel.Design.ComponentEventHandler.Invoke(Object sender, ComponentEventArgs e)

    at System.ComponentModel.Design.DesignerHost.RemoveFromContainerPostProcess(IComponent component, IContainer container)

    at System.ComponentModel.Design.DesignerHost.Remove(IComponent component)

    Obviously the problem is deeper.....

    Thanks anyway!

    Daniel


  • bfellner

    the custom designer of the control should be able to keep track of the created sub components and should be able to iterate on them easily


  • Qing

    Perhabs you can cast RootComponent to IContainer and enumerate it's internals

  • Bringing controls out from design-time