Home All Groups Group Topic Archive Search About

can a method implement an interface and handle an event at the same time?

Author
14 Sep 2006 11:33 PM
keith.thornhill
hi all,

lets say i have a usercontrol which implements a custom interface. like
so:

-------------------------------------------------

interface IMyInterface
    sub buttonClick()
end interface

class MyParentControl
    protected MyButton as Button
end class

class MyUserControl
    inherits MyParentControl
    implements IMyInterface

    sub buttonClick() implements IMyInterface.buttonClick
    end sub
end class

-------------------------------------------------

here's the catch. i want MyUserControl.buttonClick to also handle
MyButton.Click(), and i want the code that wires up that event to be in
MyParentControl, not MyUserControl.

is it possible? when i try to put "AddHandler MyButton.Click, AddressOf
Me.buttonClick" in MyParentControl, the compiler tells me that
buttonClick is not a member of MyParentControl (obviously)

not sure how i should move forward here.  putting the AddHandler call
into MyUserControl is something i'd like to avoid.

thanks!

Author
15 Sep 2006 5:15 AM
Mattias Sjögren
>is it possible?

You can do it like this

MustInherit class MyParentControl
    protected WithEvents MyButton as Button

    Protected MustOverride Sub buttonClick() Handles MyButton.Click
end class

class MyUserControl
    inherits MyParentControl
    implements IMyInterface

    Protected Overrides sub buttonClick() implements
IMyInterface.buttonClick
    end sub
end class


Mattias

--
Mattias Sjögren [C# MVP]  mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Author
15 Sep 2006 1:29 PM
keith.thornhill
true, but VS 2005 still cannot open abstract classes in design view,
which is one of the primary features of the code i am trying to write.
(the old code is abstract and i'm purposefully changing from that.)

i'm just trying to find out if there is a clean way to mimic the
abstract method definitions while avoiding abstract classes. i do
realize that i can't force any classes which inherit from
MyParentControl to also implement IMyInterface, but since interfaces
are the only other way i know of which enforce certain methods to be
defined that is the route i am trying to take.

but thank you for the suggestion

-keith

Mattias Sjögren wrote:
Show quoteHide quote
> >is it possible?
>
> You can do it like this
>
> MustInherit class MyParentControl
>     protected WithEvents MyButton as Button
>
>     Protected MustOverride Sub buttonClick() Handles MyButton.Click
> end class
>
> class MyUserControl
>     inherits MyParentControl
>     implements IMyInterface
>
>     Protected Overrides sub buttonClick() implements
> IMyInterface.buttonClick
>     end sub
> end class
>
>
> Mattias
>
> --
> Mattias Sjögren [C# MVP]  mattias @ mvps.org
> http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
> Please reply only to the newsgroup.
Author
15 Sep 2006 1:52 PM
Phill W.
keith.thornh***@gmail.com wrote:

Show quoteHide quote
> interface IMyInterface
>     sub buttonClick()
> end interface
>
> class MyParentControl
>     protected MyButton as Button
> end class
>
> class MyUserControl
>     inherits MyParentControl
>     implements IMyInterface
>
>     sub buttonClick() implements IMyInterface.buttonClick
>     end sub
> end class
>
> -------------------------------------------------
>
> here's the catch. i want MyUserControl.buttonClick to also handle
> MyButton.Click(), and i want the code that wires up that event to be in
> MyParentControl, not MyUserControl.
>
> is it possible?

The biggest problem here is that event handlets have a distinctive
signature - "name( Object, EventArgs )" - that your Interface method
doesn't have.  You're going to have to have a /separate/ routine that
does the actual work and call it from (a) the button's "click" handler
and (b) the method that implements the Interface.

Class MyParentControl

    Protected WithEvents MyButton as Button

    Sub New()
       MyButton = New Button
       With MyButton
          ...
       End With
    End Sub

    Protected Sub buttonClick()
       ' code for dealing with "Click" goes here
    End Sub

    Private Sub MyButton_Click(sender As Object, e As EventArgs) _
       Handles MyButton.Click

       Me.buttonClick()

    End Sub

End Class


Class MyUserControl
    Inherits MyParentControl
    Implements IMyInterface

    Sub New()
       MyBase.New()

    End Sub

    Private Sub Something() _
       Implements IMyInterface.buttonClick

       MyBase.buttonClick()

    End Sub

End Class

HTH,
    Phill  W.
Author
15 Sep 2006 2:13 PM
keith.thornhill
i'm sorry, i suppose i should have been more exact; my actual interface
method is defined as

Interface IBaseContractControl
        Sub ButtonClick(ByVal sender As System.Object, ByVal e As
System.EventArgs)
End Interface

(i used an empty paramter list to simplify the example, my apologies)

this (in theory) allows me to use a single function located in
MyUserControl which can satisfy the interface and be directly wired up
to the event.  i'm just not sure how to wire it up at run time from
MyParentControl. (instead of, for example, calling "AddHandler
MyButton.Click, AddressOf ButtonClick" in MyUserControl's constructor)

-keith

Phill W. wrote:
Show quoteHide quote
> keith.thornh***@gmail.com wrote:
>
> > interface IMyInterface
> >     sub buttonClick()
> > end interface
> >
> > class MyParentControl
> >     protected MyButton as Button
> > end class
> >
> > class MyUserControl
> >     inherits MyParentControl
> >     implements IMyInterface
> >
> >     sub buttonClick() implements IMyInterface.buttonClick
> >     end sub
> > end class
> >
> > -------------------------------------------------
> >
> > here's the catch. i want MyUserControl.buttonClick to also handle
> > MyButton.Click(), and i want the code that wires up that event to be in
> > MyParentControl, not MyUserControl.
> >
> > is it possible?
>
> The biggest problem here is that event handlets have a distinctive
> signature - "name( Object, EventArgs )" - that your Interface method
> doesn't have.  You're going to have to have a /separate/ routine that
> does the actual work and call it from (a) the button's "click" handler
> and (b) the method that implements the Interface.
>
> Class MyParentControl
>
>     Protected WithEvents MyButton as Button
>
>     Sub New()
>        MyButton = New Button
>        With MyButton
>           ...
>        End With
>     End Sub
>
>     Protected Sub buttonClick()
>        ' code for dealing with "Click" goes here
>     End Sub
>
>     Private Sub MyButton_Click(sender As Object, e As EventArgs) _
>        Handles MyButton.Click
>
>        Me.buttonClick()
>
>     End Sub
>
> End Class
>
>
> Class MyUserControl
>     Inherits MyParentControl
>     Implements IMyInterface
>
>     Sub New()
>        MyBase.New()
>
>     End Sub
>
>     Private Sub Something() _
>        Implements IMyInterface.buttonClick
>
>        MyBase.buttonClick()
>
>     End Sub
>
> End Class
>
> HTH,
>     Phill  W.
Author
15 Sep 2006 2:35 PM
Chris Dunaway
keith.thornh***@gmail.com wrote:
Show quoteHide quote
> i'm sorry, i suppose i should have been more exact; my actual interface
> method is defined as
>
> Interface IBaseContractControl
>         Sub ButtonClick(ByVal sender As System.Object, ByVal e As
> System.EventArgs)
> End Interface
>
> (i used an empty paramter list to simplify the example, my apologies)
>
> this (in theory) allows me to use a single function located in
> MyUserControl which can satisfy the interface and be directly wired up
> to the event.  i'm just not sure how to wire it up at run time from
> MyParentControl. (instead of, for example, calling "AddHandler
> MyButton.Click, AddressOf ButtonClick" in MyUserControl's constructor)

You will need to add an event to your user control that is exposed to
your controls parent.  Then inside your button click, you need to raise
that event.
Author
15 Sep 2006 3:46 PM
keith.thornhill
thank you everyone for the help.

here is how i solved it:

this method was added to MyParentControl

Private Function AddInterfaceHandler(ByVal EventName As String, ByVal
InterfaceMethod As String) As Boolean

        Dim objType As Type
        Dim deleg As System.Delegate
        Dim evInfo As System.Reflection.EventInfo

        Try
            objType = GetType(BaseContractControl(Of Thelper, Tsps))
            evInfo = objType.GetEvent(EventName)
            deleg =
System.Delegate.CreateDelegate(evInfo.EventHandlerType, Me,
InterfaceMethod)
            evInfo.AddEventHandler(Me, deleg)

            Return True
        Catch ex As Exception
            ' derived must have not implemented the interface

            Return False
        End Try

    End Function

this function could easily be made to wire directly to the objects
firing the events (i.e. the button) if you add a "Target as Object"
parameter and change the final "AddEventHandler" call to pass that
object rather than Me.

but since i've adjusted MyParentControl to handle the button click
event directly and then fire off its own event, i could hardcode that
call.

-keith

Chris Dunaway wrote:
Show quoteHide quote
> keith.thornh***@gmail.com wrote:
> > i'm sorry, i suppose i should have been more exact; my actual interface
> > method is defined as
> >
> > Interface IBaseContractControl
> >         Sub ButtonClick(ByVal sender As System.Object, ByVal e As
> > System.EventArgs)
> > End Interface
> >
> > (i used an empty paramter list to simplify the example, my apologies)
> >
> > this (in theory) allows me to use a single function located in
> > MyUserControl which can satisfy the interface and be directly wired up
> > to the event.  i'm just not sure how to wire it up at run time from
> > MyParentControl. (instead of, for example, calling "AddHandler
> > MyButton.Click, AddressOf ButtonClick" in MyUserControl's constructor)
>
> You will need to add an event to your user control that is exposed to
> your controls parent.  Then inside your button click, you need to raise
> that event.