Need some advice on a simple Class (1 Viewer)

on your demo, the Ribbon is showing, will it be shown on the Actual db?
if it is, you also need to code when users click the Filter (Asc/Desc) or click the Remove filter so that your label will
respond to the change.
Good point, but at this point, my sole aim is to learn how to pass different count of the same type of controls to a class and make them all behave the same.

If I take this to our DB, we would be safe, because our ribbon is set to startFromScratch='true' and we don't have Sort options in any of its 9 tabs.
All our continuous forms, rely on two public functions that add this sort functionality. But getting familiar with this method and understanding how it works, I'm tempted to add it.

Thanks.
 
> But 3 classes for a simple task like this is too much.
yes it is overkill.
In my opinion, the number of classes doesn't say much about overkill.
A few more classes can certainly achieve a better separation of responsibilities and if a few generally usable classes are then created, I even see this as an advantage.

Attached is my suggestion for the task in #1
 

Attachments

i also will stick with my 3 class
 

Attachments

Good point, but at this point, my sole aim is to learn how to pass different count of the same type of controls to a class and make them all behave the same
If you look at these three approaches they are all slightly different versions of the same general techniques. Each version is slightly more encapsulated and as
@Josef P. states this is good.
A few more classes can certainly achieve a better separation of responsibilities and if a few generally usable classes are then created, I even see this as an advantage.
1. All three approaches have a composition class that holds the labels and basically extends the properties of that label and captures the label events. In other languages that really supported OOP you would not do this. You would create a class (in my case SortableLabel) that inherits a Label and truly extends the methods and properties of a label. However VBA does not support inheritance so you have to build a composite class that has a label as a class property and uses with events.
2. All approaches then have a class that holds the instances of the class. I call this a collection class.
3. All approaches trap the label event of the instances held in the collection and then call a procedure that raises a common event that can be trapped somewhere else.

If you look at what @arnelgp did this is a more fundamentally correct version of what I did. He created a Listener Class / Notifier class where the instances call an procedure that raises the event then you only have to listen to a single event raised by the notifier / listener class. As I said my approach seems a little quirky in that the collection class is also the notifier. This means the label instances have to know about their own collection as they are created. It works but not fundamentally correct IMO.

So bottom line, it is some modified version of this.
1. Create your "label" class that brings in the label using withevents to trap its events. Create all the additional properties. This class knows nothing of other custom labels and does not do any of the processing of the filtering and property setting.
2. Create some kind of a collection class to hold your custom labels.
3. Create some kind of listener that your custom labels call a method to then raise a single custom method.
In my case I did not really raise another event, but did the processing directly in the collection class.
4. Have the collection class do the processing.
 
How to add a new event to your class? (For now the file in #15)
Not sure if you are aware of this. If not this is a huge time saver.

When you add a class variable with Events you then can choose from the drop down to add the events just like any form or control object.
So m_label is added with events as a label object. It then appears in the pulldown.
WithEvents.jpg


Once you select from the left pulldown you can add the events from the right.

WithEvents2.jpg


More important this works with classes that raise custom events like my SortableLabels class

WithEvents3.jpg
 
In other languages that really supported OOP you would not do this. You would create a class (in my case SortableLabel) that inherits a Label and truly extends the methods and properties of a label.
... or implement via dependency injection. I find this more elegant, as you can program it against an interface.
(Particularly when you keep in mind that Access.Label is an interface and not a class ;))
 
Last edited:
@KitaYama

Using the notifier / listener idea here may be a somewhat simpler idea. This is how you can do what you asked originally
I was looking for a way to access or write a property for each instance, or find a way to make each instance being able to communicate with each other.
This simplifies because you do not need a collection class anywhere. No need to loop the controls because each control listens to the other click events and decides what to do based on "who" was clicked.

Each Instance of SortableLabel announces to the Notifier that they were clicked, then the notifier broadcasts out who was clicked, and each instance listens to the notifier to see who was clicked.

Could you instead have each SortableLabel listen to every other SortableLabel? You could but then every instance would have to hold a reference to every other instance. This would be a pain to intantiate and load. You would first have to create each instance. Then go back and add a reference to every other instance. This way every instance only has to know about the notifier.

SortableLabelNotifier
Code:
Public Event LabelClicked(TheSortableLabel As SortableLabel)

Public Sub NotifyClicked(TheSortableLabel As SortableLabel)
  RaiseEvent LabelClicked(TheSortableLabel)
End Sub

Now the SortableLabel both announces it was clicked, and listen to all the other clicks. Each instance determines what to do if it was clicked or some other label was clicked.
Code:
Option Compare Database
Option Explicit

Private WithEvents m_Label As Access.Label
Private WithEvents m_Notifier As SortableLabelNotifier
Private m_SortField As String
Private m_ParentForm As Access.Form
Private m_SortFontColor As Long
Private m_DefaultFontColor As Long

'****************************************************************************************************************************************************************
'-----------------------------------------------------------------------------------   Initialize   -------------------------------------------------------------
'*****************************************************************************************************************************************************************

Public Sub Initialize(TheNotifier As SortableLabelNotifier, TheLabel As Access.Label, TheSortField As String, Optional TheSortFontColor = vbRed)
  Set Me.Label = TheLabel
  Me.sortfield = TheSortField
  Set Me.Notifier = TheNotifier
  Set Me.ParentForm = TheLabel.Parent
  Me.SortFontColor = TheSortFontColor
  Me.DefaultFontColor = TheLabel.ForeColor
  Me.Label.OnClick = "[Event Procedure]"
End Sub

'****************************************************************************************************************************************************************
'-----------------------------------------------------------------------------------   Properties   -------------------------------------------------------------
'*****************************************************************************************************************************************************************

Public Property Get Label() As Access.Label
    Set Label = m_Label
End Property
Public Property Set Label(ByVal objNewValue As Access.Label)
    Set m_Label = objNewValue
End Property

Public Property Get sortfield() As String
    sortfield = m_SortField
End Property
Public Property Let sortfield(ByVal sNewValue As String)
    m_SortField = sNewValue
End Property
Public Property Get ParentForm() As Access.Form
    Set ParentForm = m_ParentForm
End Property
Public Property Set ParentForm(ByVal objNewValue As Access.Form)
    Set m_ParentForm = objNewValue
End Property
Public Property Get SortFontColor() As Long
    SortFontColor = m_SortFontColor
End Property

Public Property Let SortFontColor(ByVal lNewValue As Long)
    m_SortFontColor = lNewValue
End Property

Public Property Get DefaultFontColor() As Long
    DefaultFontColor = m_DefaultFontColor
End Property

Public Property Let DefaultFontColor(ByVal lNewValue As Long)
    m_DefaultFontColor = lNewValue
End Property
Public Property Get Notifier() As SortableLabelNotifier
    Set Notifier = m_Notifier
End Property

Public Property Set Notifier(ByVal objNewValue As SortableLabelNotifier)
    Set m_Notifier = objNewValue
End Property

'****************************************************************************************************************************************************************
'-----------------------------------------------------------------------------------  Announce to Notifier that You are Clicked----------------------------------------------------
'*****************************************************************************************************************************************************************

Private Sub m_Label_Click()
  'call procedure to raise event
  Me.Notifier.NotifyClicked Me
End Sub
'****************************************************************************************************************************************************************
'-----------------------------------------------------------------------------------   Listen to All Clicks and determine who and what to do -----------------------------------------------
'*****************************************************************************************************************************************************************


Private Sub m_Notifier_LabelClicked(TheSortableLabel As SortableLabel)
  'Each instance calls a method in the Notifier which raises an event then all instances listen for any notifier event raised
  If TheSortableLabel Is Me Then
    sortForm
  Else
    ReturnDefaults
  End If
End Sub
'****************************************************************************************************************************************************************
'-----------------------------------------------------------------------------------   Class Methods   -------------------------------------------------------------
'*****************************************************************************************************************************************************************
Public Sub sortForm()  
  'called when a trapped notifier event was triggered by this instance
  Me.ParentForm.OrderBy = Me.sortfield
  Me.Label.ForeColor = Me.SortFontColor
  Me.Label.FontBold = True
  Me.ParentForm.OrderByOn = True
End Sub
Private Sub ReturnDefaults()
  Me.Label.FontBold = False
  Me.Label.ForeColor = Me.DefaultFontColor
End Sub

Then on the form
Code:
Private Notifier As New SortableLabelNotifier
    'called when a trapped notifier event was not triggered by this instance
Private SLS As New Collection ' something to hold your instances

Private Sub Form_Load()
  Dim SL As SortableLabel
  Dim ctrl As Access.Control
  Dim lbl As Access.Label
  For Each ctrl In Me.Controls
    If ctrl.Tag <> "" Then
      Set SL = New SortableLabel
      Set lbl = ctrl
      SL.Initialize Notifier, lbl, lbl.Tag
      SLS.Add SL, lbl.Tag
    End If
  Next ctrl
End Sub
 

Attachments

Last edited:
I really appreciate all the efforts everyone's putting on this post to help me learn.
I was too busy with my job and couldn't check @arnelgp and @Josef P. 's solutions.
Just finished @MajP's #17 and moving to later posts.
I think now I have better view of how things are done.

Million thanks to all.
 

Users who are viewing this thread

Back
Top Bottom