Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does a Winforms Control raise an event when it is added to a form

I'm working on some custom Control classes and need to do some initialization on them which is dependent on them being added to a form. Is there an event that fires when this happens?

I think this sample should be sufficient to show what I'm trying to do:

public interface IMyForm
{
    ISomeObject SomeObject {get; set; }
}

class MyForm : IMyForm
{
    //eg InitializeComponent() as well as several others called at later points
    private MethodThatAddsAControl()  
    {
        MyControl newControl = new MyControl();
        //other initialization as needed

        //does this raise an event in MyControl I can use to call
        //InitializationAfterBeingAddedToForm()?
        this.Controls.Add(newControl);   
    }
}


class MyControl : Control
{
    InitializationAfterBeingAddedToForm()
    {
        //can't be done in the constructor because at that point FindForm() will return null
        (FindForm() as IMyForm).SomeObject.AnEvent += new EventHandler(SomeObject_AnEvent);
    }
}

This is turning out to be more difficult than I initially realized, and I think I'm going to have to combine the suggestions from Bolu and Mike Dour. The problem is that while some MyControls are added directly to the form in which case Bolu's solution works perfectly. Others are added to panels instead of being added directly to the form. I think I've cobbled together a solution involving Bolu's solution for the former case with a few modifications to handle the case where the event is being raised by the panel being added, not the MyControl within it, and Mikes to handle the case of MyControls being added to the panel after the constructor has finished running. I'll have to test this more tomorrow morning before I feel confident that it worked.

Error message requested by Bolu when I try using his suggestion in the designer:

Failed to create component 'MyControl'.  The error message follows:
 'System.MissingMethodException: Constructor on type 'MyNamespace.MyControl' not found.
   at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
   at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
   at System.ComponentModel.Design.DesignSurface.CreateInstance(Type type)
   at Microsoft.VisualStudio.Design.VSDesignSurface.CreateInstance(Type type)
   at System.ComponentModel.Design.DesignerHost.System.ComponentModel.Design.IDesignerHost.CreateComponent(Type componentType, String name)
   at System.ComponentModel.Design.DesignerHost.System.ComponentModel.Design.IDesignerHost.CreateComponent(Type componentType)
   at System.Drawing.Design.ToolboxItem.CreateComponentsCore(IDesignerHost host)
   at System.Drawing.Design.ToolboxItem.CreateComponentsCore(IDesignerHost host, IDictionary defaultValues)
...'

And the constructors in place when I got the error.

public MyControl(Form parent)
{
    _parent = parent as IMyForm;
    parent.ControlAdded += new ControlEventHandler(parent_ControlAdded);
    Initialize();  //does rest of initialization
}

public TimelineControl(Form parent, Panel container)
{
    _parent = parent as IMyForm;
    container.ControlAdded += new ControlEventHandler(parent_ControlAdded);
    Initialize();  //does rest of initialization
}
like image 315
Dan Is Fiddling By Firelight Avatar asked Nov 23 '10 16:11

Dan Is Fiddling By Firelight


2 Answers

Try the ParentChanged event.

like image 83
Mike Dour Avatar answered Sep 19 '22 09:09

Mike Dour


  1. add a new MyForm object in MyControl

    MyForm pForm;

  2. pass a MyForm reference to MyControl when create it:

    MyControl newControl = new MyControl(this);

  3. then register ControlAdded event of your MyForm object

    pForm.ControlAdded+=new ControlEventHandler(pForm_ControlAdded);

Based on your code, it should looks something like:

class MyForm : IMyForm
{
    private MethodThatAddsAControl()  //includes includes InitializeComponent as well as several others called at later
    {
        MyControl newControl = new MyControl(this);
        //other initialization as needed
        this.Controls.Add(newControl);   //this will raise MyControl ::pForm_ControlAdded
    }
}


class MyControl : Control
{
    Myform pForm;
    public MyControl(MyForm ff)
    {
      InitializeComponent();
      pForm=ff;
      pForm.ControlAdded+=new ControlEventHandler(pForm_ControlAdded);
    }

}

EDIT: for the MyControl you want add to a panel, just pass the panel's reference to MyControl:

class MyForm : IMyForm
        {
            private MethodThatAddsAControl()  //includes includes InitializeComponent as well as several others called at later
            {
             //create a MyControl object and add it to MyForm
               MyControl newControl = new MyControl(this);
             //other initialization as needed
              this.Controls.Add(newControl);   //this will raise MyControl::pForm_ControlAdded

                //create a MyControl object and add it to MyPanel1
                MyControl newControl = new MyControl(MyPanel1); //pass panel reference            
                MyPanel1.Controls.Add(newControl);   //this will raise MyControl::pPanel_ControlAdded
            }
        }


    class MyControl : Control
    {

        //// for control added to Form
         Myform pForm;
         public MyControl(MyForm ff)
         {
           InitializeComponent();
           pForm=ff;
           pForm.ControlAdded+=new ControlEventHandler(pForm_ControlAdded);
         }

   ///now for control added to panel
        MyPanel pPanel;
        public MyControl(MyPanel pp)
        {
          InitializeComponent();
          pPanel=pp;
          pPanel.ControlAdded+=new ControlEventHandler(pPanel_ControlAdded);
        }

    }
like image 30
Bolu Avatar answered Sep 20 '22 09:09

Bolu