Click here to Skip to main content
15,889,877 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
I have a control that can only be implemented in specific situations (eg: it can only be added to the ControlCollection of a specific panel or form). To achieve this, I have overridden the OnParentChanged method of the control to see if the parent has implemented a given interface:
VB
Public Class MyControl

Private MyParentControl As IMyControlInterface

Protected Overrides Sub OnParentChanged(ByVal e As System.EventArgs)
    If MyBase.Parent IsNot Nothing Then
        Me.MyParentControl = TryCast(MyBase.Parent, IMyControlInterface)
        If Me.MyParentControl Is Nothing Then
            Throw New Exception("Control can only be added to an object that implements IMyControlInterface.")
        End If
    End If
    MyBase.OnParentChanged(e)
End Sub

End Class


I am trying to enable this code so that the control can be dragged from the controls panel of the Visual Basic designer to the design surface. I have defined the panel as:
VB
Public Class MyControlPanel
    Inherits Panel
    Implements IMyControlInterface

    ...

End Class


and the form is designer-generated (ie: a PartialClass extension of the form), to wit:
VB
Public Class Form1
    Implements IMyControlInterface

    ...

End Class


For some reason, when I drag MyControl to the form from the controls panel, it invokes the exception. However, when I drag MyControlPanel to the form, and then drag MyControl onto MyControlPanel1 (the name given by the designer), it accepts the dragged control.

I do not understand why one invocation accepts the add, while the other does not. Does anyone have any idea about this?

I thank you in advance for your help...
Posted
Comments
Sergey Alexandrovich Kryukov 27-Jan-11 18:57pm    
The question is not bad, interesting technique used for enforcing parent-children relationship constrain. However, it looks like suspect part of code is not presented.
--SA
grcook00 27-Jan-11 20:16pm    
SA -


I appreciate your comment on my technique. However, I do not know what the "suspect" part of code would be that I have not presented. To that end, I created a virgin VB Express project and modified the code for class Form1 as follows:

Public Class Form1
Implements IMyControlInterface

'...

End Class

Public Interface IMyControlInterface

End Interface

Public Class MyControl
Inherits Control

Private MyParentControl As IMyControlInterface


Protected Overrides Sub OnParentChanged(ByVal e As System.EventArgs)

If MyBase.Parent IsNot Nothing Then

Me.MyParentControl = TryCast(MyBase.Parent, IMyControlInterface)

If Me.MyParentControl Is Nothing Then

Throw New Exception("Control can only be added to an object that implements IMyControlInterface.")

End If
End If
MyBase.OnParentChanged(e)
End Sub

End Class

Public Class MyControlPanel
Inherits Panel
Implements IMyControlInterface


'...
End Class

This is basically the same as the original code snippets above, except that I added inheritance for class MyControl (as Control) and included a blank implementation of IMyControlInterface (as it is, so far, in my own code). I still get the same results: dragging MyControl to Form1 invokes the exception, and dragging it to MyControlPanel1 on Form1 does not.

Perhaps Manfred's answer is correct, although I do not pretend to understand its reasoning. I have also responded to that answer, to see if Manfred (or anyone else) can offer an alternative...

1 solution

Please see "Answer 1" on this page as it just about explains your pains: http://stackoverflow.com/questions/4546311/c-windows-forms-design-time-form-constructor-not-called[^]

"This behavior is by design. The form designer in Visual Studio cannot instantiate the class being designed — instead, it instatiates its immediate parent. There is no way to change this behavior. If you need some logic to be executed during design time, you have to create a separate ancestor encapsulating that logic and inherit from it."

Ondrej Tucny on stackoverflow
 
Share this answer
 
v3
Comments
grcook00 27-Jan-11 20:21pm    
Thank you, Manfred, for your suggestion. Although I cannot refute that this may be by design, there must certainly be a workaround. As I am unable to edit the Designer-Generated Code, could I, perhaps, create a Form class that the designer would properly interpret? Or is there some other way that I can perform my original task (that is, to allow my Class to only be instantiated against certain controls of varying types (derived from Form and Panel), and defining methods and properties that the implementing controls must have)?

Thanks again for any and all suggestions!
grcook00 27-Jan-11 20:43pm    
I guess I may have answered my own question. What I need to do is add the control programmatically in the constructor (rather than dropping it via the designer); then all seems to work as expected (at least in the bare-bones version). I hope that this also works once the bones have been filled in; it would also be nice to be able to use the GUI for property value modification, which I cannot do with this workaround (the designer does not show a property grid for late-added controls...). If anyone else has a workaround, please let me know!
Manfred Rudolf Bihy 28-Jan-11 5:22am    
The problem is not your control it's the form. At design time the type of the form is System.Windows.Form the immediate ancestor of your form. So what you have to do is create a form class say MyBaseForm this form implements IMyControlInterface and the form you want to create in the designer will have to inherit from MyBaseForm. To make sure MyBaseForm isn't used directly I would make it abstract.
Espen Harlinn 30-Jan-11 15:55pm    
Good work

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900