Interface Methods with Handles

false74

Well-known member
Joined
Aug 4, 2010
Messages
76
Programming Experience
Beginner
I have a small application that consists of multiple forms that each need to have the ability to be updated (not repainted, the data/components values redefined) when called to. So for instance, if I had a form that contained a count of some sort and another form modified that count I would need to update the form that displays the current count. With that being said it needs to implement an interface with these methods (see below). My issue comes when I want to add events to these methods so if I call the UpdateData event it would trigger the OnDataUpdate method, but because of the syntax of implementing methods and handling events you cannot do so.

VB.NET:
Public Interface Updatable
    Event DataUpdate()
    Event DataUpdated()

    '''<summary>ran when event DataUpdate raised, will update form's component values</summary>
    Sub OnDataUpdate()
End Interface

So when it is implemented I would need to have:

VB.NET:
Public Sub OnDataUpdate() Implements Updatable.OnDataUpdate, Handles Me.DataUpdate 'this cannot be done here!
     'code here
     RaiseEvent DataUpdated
End Sub

Is there a better way to accomplish this or would I just need to create my own handle at runtime?
 
That last code snippet doesn't make any sense anyway. Why would you be raising an event and handling it in the same method? If you did that then when you raised the event you would handle it and then rasie it again and then handle it again and then... on an on, ad infinitum. Your object raises the event but some other object handles it, e.g. a Button has an OnClick method that raises its Click event and then a Form handles that event.

On an unrelated note, unless you have a very good reason for doing otherwise, which you don't, you should follow .NET Framework conventions. These include beginning all interface names with an "I". Also, if you want a pair of events to be raised before and after some data is updated, they should be named DataUpdating and DataUpdated. Finally, all your events should be type EventHandler, EventHandler(Of TEventArgs) or some custom delegate type whose name ends with "EventHandler" and has two parameters of types Object and some type derived from EventArgs. You may like to follow the Custom Events link in my signature for more info if required.
 
Also, methods that raise events should be Protected, not Public, so they shouldn't even be part of an interface definition. Noone using an object of that type cares how the event is raised, just that they can handle it, so why would the method that raises the event need to be Public and why would it need to be defined by the interface?
 
That last code snippet doesn't make any sense anyway. Why would you be raising an event and handling it in the same method? If you did that then when you raised the event you would handle it and then rasie it again and then handle it again and then... on an on, an infinitum.
The method is raised on DataUpdate but the method itself raises DataUpdated (not DataUpdate), so there is no looping issue.

After reading your blog post about events I have changed the way I implement my interface, however I still have one question, is this the best way to handle my situation? Using an interface to define if the form/class can be updated?

VB.NET:
Public Interface IUpdatable
    Event DataUpdating As EventHandler 'once method is raised by this event it will need to raise the dataupdated event at the end
    Event DataUpdated As EventHandler 'raised once dataupdating is complete
    Sub OnDataUpdate(ByVal e As EventArgs) 'only raises the dataupdating event
End Interface
 
Also, methods that raise events should be Protected, not Public, so they shouldn't even be part of an interface definition. Noone using an object of that type cares how the event is raised, just that they can handle it, so why would the method that raises the event need to be Public and why would it need to be defined by the interface?

The reason I am using an Interface is because I have multiple forms that are different from one another, some do not have the same base class and some do not need to be updatable at all. The best solution I have/know is it just make it an interface so any class that needs the ability to be updated can be and all I would need to do is to check if that form implements the updatable interface. Which is probably the most incorrect way to do things, but it is the only solution I can think of. This is why I am asking the question.
 
It sounds to me like you want something like this:
Imports System.ComponentModel

Public Interface IUpdatable

    Property Data() As Object

    Event DataUpdating As EventHandler(Of ObjectUpdatingEventArgs)
    Event DataUpdated As EventHandler

End Interface


Public Class ObjectUpdatingEventArgs
    Inherits CancelEventArgs

    Private _data As Object

    Public ReadOnly Property Data() As Object
        Get
            Return Me._data
        End Get
    End Property

    Public Sub New(data As Object)
        Me._data = data
    End Sub

End Class
implemented like this:
Public Class Form1
    Implements IUpdatable

    Private _data As Object

    
    Public Property Data As Object Implements IUpdatable.Data
        Get
            Return Me._data
        End Get
        Set(value As Object)
            If Me._data IsNot value Then
                Dim e As New ObjectUpdatingEventArgs(value)

                Me.OnDataUpdating(e)

                If Not e.Cancel Then
                    Me._data = value
                    Me.OnDataUpdated(EventArgs.Empty)
                End If
            End If
        End Set
    End Property


    Public Event DataUpdating(sender As Object, e As ObjectUpdatingEventArgs) Implements IUpdatable.DataUpdating

    Public Event DataUpdated(sender As Object, e As EventArgs) Implements IUpdatable.DataUpdated


    Protected Overridable Sub OnDataUpdating(e As ObjectUpdatingEventArgs)
        RaiseEvent DataUpdating(Me, e)
    End Sub

    Protected Overridable Sub OnDataUpdated(e As EventArgs)
        RaiseEvent DataUpdated(Me, e)
    End Sub

End Class
or with a method instead of :
Public Interface IUpdatable

    Sub UpdateData(data As Object)

    Event DataUpdating As EventHandler(Of ObjectUpdatingEventArgs)
    Event DataUpdated As EventHandler

End Interface
implemented like this:
Public Class Form1
    Implements IUpdatable

    Private _data As Object


    Public Event DataUpdating(sender As Object, e As ObjectUpdatingEventArgs) Implements IUpdatable.DataUpdating

    Public Event DataUpdated(sender As Object, e As EventArgs) Implements IUpdatable.DataUpdated


    Public Sub UpdateData(ByVal data As Object) Implements IUpdatable.UpdateData
        If Me._data IsNot data Then
            Dim e As New ObjectUpdatingEventArgs(data)

            Me.OnDataUpdating(e)

            If Not e.Cancel Then
                Me._data = data
                Me.OnDataUpdated(EventArgs.Empty)
            End If
        End If
    End Sub

    Protected Overridable Sub OnDataUpdating(e As ObjectUpdatingEventArgs)
        RaiseEvent DataUpdating(Me, e)
    End Sub

    Protected Overridable Sub OnDataUpdated(e As EventArgs)
        RaiseEvent DataUpdated(Me, e)
    End Sub

End Class
I think that my blog post demonstrates something similar.
 
Back
Top