Вызывает ли элемент управления Winforms событие при добавлении в форму - PullRequest
8 голосов
/ 23 ноября 2010

Я работаю над некоторыми пользовательскими Control классами и мне нужно выполнить их инициализацию, которая зависит от того, будут ли они добавлены в форму.Есть ли событие, которое срабатывает, когда это происходит?

Я думаю, что этого примера должно быть достаточно, чтобы показать, что я пытаюсь сделать:

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);
    }
}

Это оказывается более труднымчем я первоначально понял, и я думаю, что мне придется объединить предложения Болу и Майка Даура.Проблема в том, что хотя некоторые MyControl добавляются непосредственно в форму, в этом случае решение Болу работает отлично.Другие добавляются на панели, а не добавляются непосредственно в форму.Я думаю, что я собрал воедино решение, включающее решение Bolu для первого случая, с несколькими модификациями для обработки случая, когда событие вызывается добавляемой панелью, а не MyControl внутри нее, и Майка для обработки случаяMyControl s добавляется на панель после завершения работы конструктора.Я должен буду проверить это больше завтра утром, прежде чем я буду уверен, что это сработало.

Сообщение об ошибке, запрошенное Болу, когда я пытаюсь использовать его предложение в конструкторе:

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)
...'

Иконструкторы на месте, когда я получил ошибку.

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
}

Ответы [ 3 ]

10 голосов
/ 23 ноября 2010

Попробуйте событие ParentChanged.

1 голос
/ 23 ноября 2010
  1. добавить новый MyForm объект в MyControl

    MyForm pForm;

  2. передать MyForm ссылку на MyControl при создании:

    MyControl newControl = new MyControl (this);

  3. затем зарегистрируйте ControlAdded событие вашего MyForm объекта

    pForm.ControlAdded+=new ControlEventHandler(pForm_ControlAdded);

Исходя из вашего кода, он должен выглядеть примерно так:

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);
    }

}

РЕДАКТИРОВАТЬ: для MyControl, к которому вы хотите добавитьпанель, просто передайте ссылку на панель в 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);
        }

    }
0 голосов
/ 23 ноября 2010

Почему бы вам не реализовать пользовательское событие в MyControl?

В этой статье описывается метод:

http://ondotnet.com/pub/a/dotnet/2002/04/15/events.html

...