Results 1 to 7 of 7

Thread: [RESOLVED] Raise / sink events defined in parent class

  1. #1

    Thread Starter
    New Member
    Join Date
    Jan 2008
    Posts
    4

    Resolved [RESOLVED] Raise / sink events defined in parent class

    I designed a base class which has events:


    Code:
    Public Class clsProxyProgress
        Public Event evProcessName(ByVal strProcessName As String)
        Public Event evDirectory(ByVal strDirectory As String)
        Public Event evCurrentFile(ByVal strCurrentFile As String)
        Public Event evFilesCompleted(ByVal intFilesCompleted As Integer)
        Public Event evFileCnt(ByVal intFileCnt As Integer)
        Public Event evRowsCopied(ByVal intRowsCopied As Long)
        Public Event evStatus(ByVal strStatus As String)
    I then inherit that class in a child class.

    Code:
    Public Class clsCSVDataExportSpec
        Inherits clsProxyProgress
    The child class clsCSVDataExportSpec cannot "see" the events in the parent, i.e. it cannot do:

    Code:
        RaiseEvent evStatus(mstrStatus)
    even though its parent class has that event. If I try to do this in the child class I get a compile error.

    In order to get around this I created functions in the parent class clsProxyProgress

    Code:
        Public Sub mStatus(ByVal strStatus As String, ByVal blnStatusReset As Boolean, ByVal blnStatusTimeStamp As Boolean)
            If blnStatusReset Then mstrStatus = ""
    
            If blnStatusTimeStamp Then
                mstrStatus = mstrStatus & vbCrLf & Now()
            End If
            If Len(mstrStatus) > 0 Then
    
                mstrStatus = mstrStatus & vbCrLf & strStatus
            Else
                mstrStatus = strStatus
            End If
    
            RaiseEvent evStatus(mstrStatus)
        End Sub
    NOTICE that in the last line of the sub I raise the evStatus. I then call this sub from the child clsCSVDataExportSpec so that the parent class clsProxyProgress raises the event for the child class. I do this simply because if I try to raise the event up in the parent class directly from the child class I get a compile error.

    The whole point of this stuff is to allow a form to sink events and display data in text boxes on the form.

    In a form class I dimension a variable for this child class:

    Code:
        Private WithEvents fclsCSVDataExport As clsCSVDataExportSpec
    further down I "sink" the events for this class:

    Code:
        Private Sub fclsCSVDataExport_evStatus(ByVal strStatus As String) Handles fclsCSVDataExport.evStatus
            txtStatus.Text = strStatus
            Application.DoEvents()
        End Sub
    In the "Handles ..." the evStatus is a choice in the intellisense dropdown, IOW this form's module "sees" the event that the child class fclsCSVDataExport inherits from its parent class clsProxyProgress. However the sub fclsCSVDataExport_evStatus() never receives control when the Raisevent is executed.

    I SUSPECT that the issue is that the "Handles ..." needs to be "Handles fclsProxyProgress", i.e. it needs to "handle" the parent of fclsCSVDataExport, not fclsCSVDataExport itself.

    fclsCSVDataExport is the actual class that performs the data export for me.
    clsProxyProgress only exists to allow several different such import / export classes inherit common events and code, and I do that so that I can
    (eventually) have a generic form that dimensions a clsProxyProgress rather than having a specific import or export class such as clsCSVDataExport or clsCSVDataImport.

    If anyone is following what I am doing and can point me to how to make this work it would be appreciated.

    Thanks,

    jwc

  2. #2
    Frenzied Member
    Join Date
    Aug 2006
    Posts
    1,051

    Re: Raise / sink events defined in parent class

    http://msdn2.microsoft.com/en-us/lib...w3(VS.80).aspx

    Code:
    Imports System 
    Imports System.Collections.Generic 
    Namespace BaseClassEvents 
        
        ' Special EventArgs class to hold info about Shapes. 
        Public Class ShapeEventArgs 
            Inherits EventArgs 
            Private m_newArea As Double 
            
            Public Sub New(ByVal d As Double) 
                m_newArea = d 
            End Sub 
            Public ReadOnly Property NewArea() As Double 
                Get 
                    Return m_newArea 
                End Get 
            End Property 
        End Class 
        
        ' Base class event publisher 
        Public MustInherit Class Shape 
            Protected m_area As Double 
            
            Public Property Area() As Double 
                Get 
                    Return m_area 
                End Get 
                Set 
                    m_area = value 
                End Set 
            End Property 
            ' The event. Note that by using the generic EventHandler<T> event type 
            ' we do not need to declare a separate delegate type. 
            Public Event ShapeChanged As EventHandler(Of ShapeEventArgs) 
            
            Public MustOverride Sub Draw() 
            
            'The event-invoking method that derived classes can override. 
            Protected Overridable Sub OnShapeChanged(ByVal e As ShapeEventArgs) 
                ' Make a temporary copy of the event to avoid possibility of 
                ' a race condition if the last subscriber unsubscribes 
                ' immediately after the null check and before the event is raised. 
                Dim handler As EventHandler(Of ShapeEventArgs) = ShapeChanged 
                RaiseEvent handler(Me, e) 
            End Sub 
        End Class 
        
        Public Class Circle 
            Inherits Shape 
            Private radius As Double 
            Public Sub New(ByVal d As Double) 
                radius = d 
                area = 3.14 * radius 
            End Sub 
            Public Sub Update(ByVal d As Double) 
                radius = d 
                area = 3.14 * radius 
                OnShapeChanged(New ShapeEventArgs(area)) 
            End Sub 
            Protected Overloads Overrides Sub OnShapeChanged(ByVal e As ShapeEventArgs) 
                ' Do any circle-specific processing here. 
                
                ' Call the base class event invocation method. 
                MyBase.OnShapeChanged(e) 
            End Sub 
            Public Overloads Overrides Sub Draw() 
                Console.WriteLine("Drawing a circle") 
            End Sub 
        End Class 
        
        Public Class Rectangle 
            Inherits Shape 
            Private length As Double 
            Private width As Double 
            Public Sub New(ByVal length As Double, ByVal width As Double) 
                Me.length = length 
                Me.width = width 
                area = length * width 
            End Sub 
            Public Sub Update(ByVal length As Double, ByVal width As Double) 
                Me.length = length 
                Me.width = width 
                area = length * width 
                OnShapeChanged(New ShapeEventArgs(area)) 
            End Sub 
            Protected Overloads Overrides Sub OnShapeChanged(ByVal e As ShapeEventArgs) 
                ' Do any rectangle-specific processing here. 
                
                ' Call the base class event invocation method. 
                MyBase.OnShapeChanged(e) 
            End Sub 
            Public Overloads Overrides Sub Draw() 
                Console.WriteLine("Drawing a rectangle") 
            End Sub 
            
        End Class 
        
        ' Represents the surface on which the shapes are drawn 
        ' Subscribes to shape events so that it knows 
        ' when to redraw a shape. 
        Public Class ShapeContainer 
            Private _list As List(Of Shape) 
            
            Public Sub New() 
                _list = New List(Of Shape)() 
            End Sub 
            
            Public Sub AddShape(ByVal s As Shape) 
                _list.Add(s) 
                AddHandler s.ShapeChanged, AddressOf HandleShapeChanged 
                ' Subscribe to the base class event. 
            End Sub 
            
            ' ...Other methods to draw, resize, etc. 
            
            Private Sub HandleShapeChanged(ByVal sender As Object, ByVal e As ShapeEventArgs) 
                Dim s As Shape = DirectCast(sender, Shape) 
                
                ' Diagnostic message for demonstration purposes. 
                Console.WriteLine("Received event. Shape area is now {0}", e.NewArea) 
                
                ' Redraw the shape here. 
                s.Draw() 
            End Sub 
        End Class 
        
        Class Test 
            
            Private Shared Sub Main(ByVal args As String()) 
                'Create the event publishers and subscriber 
                Dim c1 As New Circle(54) 
                Dim r1 As New Rectangle(12, 9) 
                Dim sc As New ShapeContainer() 
                
                ' Add the shapes to the container. 
                sc.AddShape(c1) 
                sc.AddShape(r1) 
                
                ' Cause some events to be raised. 
                c1.Update(57) 
                r1.Update(7, 7) 
                
                ' Keep the console window open. 
                Console.WriteLine() 
                Console.WriteLine("Press Enter to exit") 
                Console.ReadLine() 
            End Sub 
        End Class 
    End Namespace
    Last edited by FourBlades; Jan 1st, 2008 at 02:02 AM.

  3. #3

    Thread Starter
    New Member
    Join Date
    Jan 2008
    Posts
    4

    Re: Raise / sink events defined in parent class

    Thanks for the reply. I printed it out and am studying it but am not having much luck understanding the pieces and how to relate them back to my problem. It kinda looks like a "similar problem".

    What I am trying to accomplish is to have a generic form on which I display identical information from different classes. The work classes perform input from and output to files from a database. All that stuff is working. I just need to display status, things like the current file being processed, the % complete and so forth. The work classes do not NEED the status forms in order to function (thus raising events), the status is logged into files and also into tables in the databases, the status forms are just for my visually observing the process running, troubleshooting etc.

    Obviously I could just build a form for each such working class but given that they all are completely identical except for the working class sending the information, I thought I would try to use events. I understand events, IF the working class is dimensioned Withevents directly in the form used to display the status.

    My thought was that I would define a base class to define the events and a sub in the base class to raise each event, inherit that in each working class, then call the sub in the base to raise the event. All of THAT works. The problem appears to be in how to sink the events in the form.

    I am trying to have a supervisor process instantiate each working class, dimension and open the status display form (if desired), then pass in a pointer to the working class into the status form. The form stores the pointer into a withevents variable "somehow", that variable has event sinks. Eventually there may be several working classes functioning at the same time (using threads). Each process may or may not have a status form opened and dedicated to it. That will be determined by a supervisor which starts and stops the working classes and status forms. If the working class "has a status form" then the form will be opened by the supervisor and the form will be passed in a working class to monitor the events for.

    The "somehow" is my conceptual issue. The variable in the generic status form cannot be dimensioned of the type of the base class or the whole point of the excercise is lost, I now have a form specific to that working class. So the Withevent variable in the status form has to be of the base type inherited by the working class. Perhaps I can typecast the working class object passed in to the status form to be of the base class type, and store the type casted pointer. Since it is now of the base class and not the working class, then the event sinks work?

    Unfortunately I am new to this stuff as you can no doubt tell, so my command of the syntax is lacking.

    To recap, I have a base class which can rais events. It has a sub for each event to be raised. I have working classes which all inherit the base class. I have a generic status display form. I have a supervisor which instantiates a working class object, opens an instance of the status form and passes in a pointer to the working class object.

    What does not work is that the events in the display form does not correctly sink the events, i.e. control never passes to the event sink.
    Last edited by jwcolby; Jan 1st, 2008 at 10:05 AM.

  4. #4
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,106

    Re: Raise / sink events defined in parent class

    A couple things that may have already been covered, but it's early:

    1) Since you raise all the events from the base class, wouldn't you be declaring the classes in the form as WithEvents BaseClass, rather than the derived class. Every derived class should be able to be used as a pointer to its base class, so if all of the working classes are derived from a common base, you should only need to declare base classes in the form and the declared variables should be able to accept any of the derived classes. Then the normal event handling should be fine.

    2) If these classes work in separate threads, you're going to have some synchronization issues if you try to write to the UI thread from a child thread. If you've already thought that through, it won't be an issue, but raising events on the UI thread such that you can write to a control when the event fires isn't quite the same as in the single threaded model.
    My usual boring signature: Nothing

  5. #5

    Thread Starter
    New Member
    Join Date
    Jan 2008
    Posts
    4

    Re: Raise / sink events defined in parent class

    Quote Originally Posted by Shaggy Hiker
    1) Since you raise all the events from the base class, wouldn't you be declaring the classes in the form as WithEvents BaseClass, rather than the derived class. Every derived class should be able to be used as a pointer to its base class, so if all of the working classes are derived from a common base, you should only need to declare base classes in the form and the declared variables should be able to accept any of the derived classes. Then the normal event handling should be fine.

    2) If these classes work in separate threads, you're going to have some synchronization issues if you try to write to the UI thread from a child thread.
    1) Yes, that is the idea.
    2) What are the issues there? I have seen implications that you can't update controls from a worker thread but nothing specific or how to program around it. Each process class will have its own form to display in (if it has a form at all).

  6. #6

    Thread Starter
    New Member
    Join Date
    Jan 2008
    Posts
    4

    Re: Raise / sink events defined in parent class

    Woohooo, Success!!! It turns out it was as simple as passing in the derived class to a variable of the type base class in the New() of the form, then setting that base class passed in into a base class variable dimensioned WithEvents in the header of the form. Voila, the status form started working, sinking the events from the derived class.

    Thanks for your help guys, much appreciated.

  7. #7
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,106

    Re: [RESOLVED] Raise / sink events defined in parent class

    Well, if it's working, I guess we can ignore my #2 point.
    My usual boring signature: Nothing

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width