Reference error from custom event (1 Viewer)

MajP

You've got your good things, and you've got mine.
Local time
Today, 09:01
Joined
May 21, 2018
Messages
8,525
Also I can ensure you that a procedure will not function differently if the method is called directly of if it is called from a event handler reacting to a custom event. What you think is happening is not. You are mistaken about what is going on.
 

Petr Danes

Registered User.
Local time
Today, 15:01
Joined
Aug 4, 2010
Messages
150
No that is not true. You just added another class module in the middle to raise the event, but you are hard coding tightly coupling it with the global variables. This is a poor design. I will say it one more time, every event handler has a contract with the thing raising the event. You are just doing it through a class. It is an unnecessary chain.
So instead of having each form raise its own events you simulate this by calling a procedure or setting a global variable. You just centralized the event calling. THIS IS NOT encapsulation. Encapsulation is about protection of the objects. You protect the inner working and make available public and methods and variables. This is the opposite especially with all these global variables.

If I had 10 forms each changing animals, I would have ten object variables and 10 event handlers. I would not tightly couple my ten forms to a single custom class to raise a single event. That is convoluted and violates good coding.
Hm. Well, I'm not an expert on this topic, but all the reading I've done suggests that your way of 10 object variables and 10 separate event handlers is exactly the wrong way to go about such work. Maybe I'm using the word encapsulation incorrectly, but the notion is the independence of individual objects from each other. An object should not need to know who has done something in order to deal with the fact that something happened.

However, we've veered a bit away from the topic of why this is throwing an error. Regardless of which way the event procedure is constructed, a routine inside a form should know where it is and what its content are.
 

Petr Danes

Registered User.
Local time
Today, 15:01
Joined
Aug 4, 2010
Messages
150
Also I can ensure you that a procedure will not function differently if the method is called directly of if it is called from a event handler reacting to a custom event. What you think is happening is not. You are mistaken about what is going on.
I don't know what to say to that. I have stopped and stepped the code, and what I described IS exactly what is happening, which is the reason for this post. Even stopped, both in the immediate window and examining code elements from the breakpoint, that is the status. If you tell me from a distance that what I am clearly seeing is not what I am seeing, then I do not know how to respond.
 
Last edited:

MajP

You've got your good things, and you've got mine.
Local time
Today, 09:01
Joined
May 21, 2018
Messages
8,525
Hm. Well, I'm not an expert on this topic, but all the reading I've done suggests that your way of 10 object variables and 10 separate event handlers is exactly the wrong way to go about such work.

You can read my thousands of threads on this forum alone using custom classes, event handling, custom procedures, etc in vba. Then decide for yourself if I you really think I do not know what I am talking about, and you have found the correct way. Nothing you have stated so far about the theory supports your execution and design. It is apple and oranges from what you are saying to what you have implemented.

However, we've veered a bit away from the topic of why this is throwing an error. Regardless of which way the event procedure is constructed, a routine inside a form should know where it is and what its content are.
My demo clearly shows this is not an issue in general. There is no problem with doing this so there is something else wrong with your code or what you think is the problem is not. I built a procedure in my main module that has references to objects within the main and the subform. I built a event handler that calls this procedure after trapping an external event. My procedure executes without any problem. This is exactly as you describe showing that there is not issue.

Your look like you are trying to build a custom universal Caller/Listener . Again that has nothing to do with the problem you describe nor proper encapsulation.
If your goal is to have a single class raise a single event based on other forms doing things, that is not really the way to do it, but it may be the best you can do in VBA since there is no real inheritance and limited use of Interfaces. When I get time I will build a proper example of a Common Caller / Listener class.

IMO this is not good Event driven programming, but this may be a limitiation of VBA without inheritance. You have a class that raises an event. You made a reference to this object as a global variable. This class does not listen to any events, but exposes public methods which in turn will raise the the event.
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 08:01
Joined
Feb 28, 2001
Messages
27,140
Let's return to the fact that you somehow need to make a specific reference in order for this code to work. From your original post, ...

That works perfectly when the code is executed from the main form's OnCurrent event, but that same code throws an error when activated by the raised custom event from the dialog form. Some experimenting determined that I have to use a previously set reference to the main form the make this code work from the event call.

The mechanism of an event handler is different from a simple subroutine call. An event cannot "interrupt" another event because Access, being the MAIN program, already has the Windows process's interrupt handler to itself and you can't have it. If the conditions are right and an interrupt of some kind DOES trigger an event, it will place that event into a queue. And since Access is your main program, any code of yours that you are running at the moment IS executing within the context of an event or a trap handler or a .DLL/other library file or an external object e.g. Excel as an application object (only four choices). Of those, the .DLL and App Objects don't even share the same memory space. Anything they expose is solely at the call interface level. Traps are dangerous to "fool around" with because they represent a special context, too. So that leaves that anything you do is 95%+ likely to be in event context, which is linearized.

That Event Handler's caller is Access itself as it empties a FIFO queue to process all pending events. (You can verify that this queue exists by doing a focus change inside a routine and log what order applies to the event handlers with and without the focus change.) If you were to take a breakpoint, I'm not going to tell you exactly what is on the stack, but it should be at least subtly different than what is on the Call Stack from a simple subroutine call.

That being said, I believe the "detached" nature of the program flow of a custom event handler "loses" the context when compared to subroutines. The fact that this event code is defined in a special class module means that it is not tightly bound to its caller; it is only INSTANTIATED by its caller, which is a different question. Cf. event code in a form's class module calling a subroutine in the same form's class module. They share a common declaration area, among other things, and are compiled together as a unit. The custom handler is compiled in a separate module. Just the simplest difference here is that Me.x involves a COMPILE-time resolution, semantically speaking. That hypothetical subroutine within the Form's class module WOULD be resolvable at compile time. The context of that form's module is NOT visible when the event handler code in its separate class module is unable to see the things in the form's class module at compile time. That is why you have to include a more explicit reference to the parent form in your nest of forms in order for this to work.

You talk of encapsulation, but does that really apply here? You aren't talking about the form reaching IN to the guts of the special event - you are talking about the code behind the special event reaching into the form, which is ITSELF encapsulated from things outside the form, unless you make the PUBLIC declarations that allow such usage. And the only things that CAN be public are variables and function/sub entry points.
 

Petr Danes

Registered User.
Local time
Today, 15:01
Joined
Aug 4, 2010
Messages
150
You can read my thousands of threads on this forum alone using custom classes, event handling, custom procedures, etc in vba. Then decide for yourself if I you really think I do not know what I am talking about, and you have found the correct way. Nothing you have stated so far about the theory supports your execution and design. It is apple and oranges from what you are saying to what you have implemented.
I didn't claim you don't know what you're talking about. I only wrote that what I have seen from many other sources, including manuals from people I know to be knowledgeable state that separation of the sort I describe is the proper way to do such things. I do not know if I have all the details exactly correct - probably not, since it doesn't work, but gist is always that such entities should be as uncoupled as possible. Requiring a listener to know in advance who all might be speaking, and having to change source code in every possible listener each time a new speaker is added just seems wrong.


My demo clearly shows this is not an issue in general. There is no problem with doing this so there is something else wrong with your code or what you think is the problem is not. I built a procedure in my main module that has references to objects within the main and the subform. I built a event handler that calls this procedure after trapping an external event. My procedure executes without any problem. This is exactly as you describe showing that there is not issue.
Well, yes, but your demos both do it the way you describe, with the listener having to know in advance who all might be speaking, and having source code specifically naming all possible speakers. That is just not the way I want this to work.


Your look like you are trying to build a custom universal Caller/Listener . Again that has nothing to do with the problem you describe nor proper encapsulation.
If your goal is to have a single class raise a single event based on other forms doing things, that is not really the way to do it, but it may be the best you can do in VBA since there is no real inheritance and limited use of Interfaces. When I get time I will build a proper example of a Common Caller / Listener class.
Yes, that is the way I want to do it. I want the speaker and listener not to know anything about each other. I don't wish to argue with you about whether it is the 'proper' way to do it. I think it is, you think it is not. Fine - there is no requirement that we agree on everything. And often there is not a single best way to approach a problem.


IMO this is not good Event driven programming, but this may be a limitiation of VBA without inheritance. You have a class that raises an event. You made a reference to this object as a global variable. This class does not listen to any events, but exposes public methods which in turn will raise the the event.
Well, okay. I don't have a lot of experience with other event-driven languages, so I can't comment on that, but yes - I have a sort of 'commons', where various modules can raise events and others can sink events, all without any of them knowing anything about any other entity. Whether it's called encapsulation or something else, that sort of isolation is my intent.

In any case, thank you for the insights.
 

Petr Danes

Registered User.
Local time
Today, 15:01
Joined
Aug 4, 2010
Messages
150
Let's return to the fact that you somehow need to make a specific reference in order for this code to work. From your original post, ...



The mechanism of an event handler is different from a simple subroutine call. An event cannot "interrupt" another event because Access, being the MAIN program, already has the Windows process's interrupt handler to itself and you can't have it. If the conditions are right and an interrupt of some kind DOES trigger an event, it will place that event into a queue. And since Access is your main program, any code of yours that you are running at the moment IS executing within the context of an event or a trap handler or a .DLL/other library file or an external object e.g. Excel as an application object (only four choices). Of those, the .DLL and App Objects don't even share the same memory space. Anything they expose is solely at the call interface level. Traps are dangerous to "fool around" with because they represent a special context, too. So that leaves that anything you do is 95%+ likely to be in event context, which is linearized.

That Event Handler's caller is Access itself as it empties a FIFO queue to process all pending events. (You can verify that this queue exists by doing a focus change inside a routine and log what order applies to the event handlers with and without the focus change.) If you were to take a breakpoint, I'm not going to tell you exactly what is on the stack, but it should be at least subtly different than what is on the Call Stack from a simple subroutine call.

That being said, I believe the "detached" nature of the program flow of a custom event handler "loses" the context when compared to subroutines. The fact that this event code is defined in a special class module means that it is not tightly bound to its caller; it is only INSTANTIATED by its caller, which is a different question. Cf. event code in a form's class module calling a subroutine in the same form's class module. They share a common declaration area, among other things, and are compiled together as a unit. The custom handler is compiled in a separate module. Just the simplest difference here is that Me.x involves a COMPILE-time resolution, semantically speaking. That hypothetical subroutine within the Form's class module WOULD be resolvable at compile time. The context of that form's module is NOT visible when the event handler code in its separate class module is unable to see the things in the form's class module at compile time. That is why you have to include a more explicit reference to the parent form in your nest of forms in order for this to work.

You talk of encapsulation, but does that really apply here? You aren't talking about the form reaching IN to the guts of the special event - you are talking about the code behind the special event reaching into the form, which is ITSELF encapsulated from things outside the form, unless you make the PUBLIC declarations that allow such usage. And the only things that CAN be public are variables and function/sub entry points.
Whew - that's a lot to take in. I'll have to study that a bit before I can respond in any sensible fashion, but thank you for the explanation.
 

pdanes

Registered User.
Local time
Today, 06:01
Joined
Apr 12, 2011
Messages
70
So I've got it working. I was unable to pin down exact behavior to the point where I could isolate precisely when and how it 'loses track' of context, but it seems to be as you write - the context is different when I'm coming back into the form's code from a custom event handler. I don't have the expertise to dig into stack contents and the like, but observing things at the level I can, it is working as I described: code inside a form's module does not implicitly know about the contents of the form when that code is called via an event handler, the way it DOES know about those contents when called via a normal function or subroutine call, even from code outside the form.

So I went the simple route. Rather than include a specific reference to the form in code inside the form, which I could easily forget about and 'clean up' some time in the future, all such code is now in a separate code module, where explicit references to the form are required in order to even compile. A comment in the code about why the code is separated out should be sufficient to keep me from messing it up in any future work.

I have the entire thing now working exactly as I envisioned. There is a single class module in which there are all of my custom events are defined, all RaiseEvent commands are performed. I have ONE global object variable for all of this - any module wanting to raise an event calls the appropriate method in this global event handling object, and any module wishing to sink an event defines a WithEvents variable based on events defined in this class.

All custom events are defined in one place, so they are easy to troubleshoot. Any module performing an action can raise an event to let the world know it has done so, without knowing anything about who, how many or even IF anybody is listening. Any module wishing to handle an event can do so without having to know anything about who raised it, or how many different objects may be raising it. All it needs to know is that a specific thing has happened.

Whatever it is called, that sort of isolation and independence is what I was after. Many thanks to you and all others for the assistance - this was a serious learning experience.
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 09:01
Joined
May 21, 2018
Messages
8,525
All custom events are defined in one place, so they are easy to troubleshoot. Any module performing an action can raise an event to let the world know it has done so, without knowing anything about who, how many or even IF anybody is listening. Any module wishing to handle an event can do so without having to know anything about who raised it, or how many different objects may be raising it. All it needs to know is that a specific thing has happened.
Again that is not really true. All you have done is created a "centralized event raiser". Each and every object knows exactly who is raising an event, and that is the "centralized event raiser." All of your other classes and modules are not raising events. They are running a procedure in the "centralized event raiser" which in turn then raises the event. Without being exact in your verbiage, it is impossible for others to understand what you are trying to do.

And again I can guarantee 100% this is not true
but it seems to be as you write - the context is different when I'm coming back into the form's code from a custom event handler
That is not how code works. You have some other mistake somewhere in this code.
 

pdanes

Registered User.
Local time
Today, 06:01
Joined
Apr 12, 2011
Messages
70
All you have done is created a "centralized event raiser".
Yes, I have. And how is that different from the "centralized event raiser" inside the Access engine?

All of your other classes and modules are not raising events. They are running a procedure in the "centralized event raiser" which in turn then raises the event.
You could just as easily say that the RaiseEvent statement doesn't really raise the event, but runs a procedure inside Access somewhere which in turn raises the event. It might be cleaner to have the RaiseEvent statement right in the module that does the activity, but I haven't figured out any way to do that. If you know of some way to do it, OTHER THAN the way you described earlier, which requires source code coupling between event raiser and event trapper, I would be happy to hear it. However, what you described a few weeks back is exactly what I do NOT want. Your way requires the trapping module to explicitly know about every possible event-raising module, and modification of the source code every time a new event-raiser is added. That is completely against everything I have read on event handling. Access itself does nothing of the sort, and in fact, works the way I describe. When you press a key on a control, Access raises an event. The KeyPress event can be captured by anybody who is interested, regardless of how that KeyPress happened. Your way, it would be like having to have a separate event handler variable and routine for every single key that might be pressed – your 'contract' between the two modules. I don't want that – I want the routine doing something to simply broadcast that information (raise an event) and whoever is interested can react to that event. My way, any routine can do some bit of work and announce it to the world, without knowing anything about who might be interested, and any routine, or even multiple routines, can respond to that broadcast without knowing anything about who did the work. In fact, doing it your way, you do not even need an event. The routine doing the work could simply call the routine that responds to the event, since you have a one-to-one coupling between the broadcaster and responder.

And again I can guarantee 100% this is not true

That is not how code works. You have some other mistake somewhere in this code.
You wrote before that it can't be happening. Doc_man wrote me an explanation, which is pretty involved, but makes sense. All you are doing is repeating that I am not seeing something that I very clearly AM seeing. I do not know how to respond to that.
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 09:01
Joined
May 21, 2018
Messages
8,525
It is what it is, do not sell it for more than that. All you did was make a class module. You tightly couple all your other modules to call procedures in a public instance of this class. The called procedures then raise custom events. The advantage of this is that all your listeners can assign a variable of this common class and listen to its events. It is fine, if you have a legitimate reason to do this or if it is an academic exercise. But you make this sound as if this is the normal construct.
In theory this sounds great, in practicality I have never seen it done or needed to be done in an Access database. I would be curious if anyone has. The only place I have seen this construct is in Modeling and Simulation where you have multiple entities entering and leaving and each and every entity is listening to the other. Example each car moves around and at each time step broadcasts its position. If each car listens to every other car then two cars can know they crash when they announce the same location.
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 09:01
Joined
May 21, 2018
Messages
8,525
For those interested here is a simple demonstration of the OPs centralized event raiser construct. This demos that there is absolutely no problem with trapping the custom events from the centralized event handler.
In this design you have three forms. When you pick a color from the combobox each form calls the centralized event raiser and this then the class raises the event. You will see each form then can listen to that event and shows it in the textbox. I even have each form listen for the event that they pseudo raised.
I have only seen utility of this construct in simulations, but never in a real world Access database. Curious if anyone has implemented this construct. The concept could potentially take the place of some code that relies on the timer to check for an update.
 

Attachments

  • CentralizedListener.accdb
    1.5 MB · Views: 155

pdanes

Registered User.
Local time
Today, 06:01
Joined
Apr 12, 2011
Messages
70
It is what it is, ...
Sorry, I also do not know how to respond to a tautology.

But thank you for the demo. It works as you say, of course. I also tried to create my own demo to isolate and reproduce the behavior I am seeing, and was unsuccessful. In my very limited test case, the incorrect behavior also does not manifest. Nonetheless, my actual DB very much does behave as I described. I have no idea why, but I have tested it very carefully, and there is no doubt - it behaves exactly as I wrote: when the form's public routine is called directly, it works properly; when it is called via the event-raising class module, it does not know of 'itself'.

I rather doubt that it is a mistake in my code, as you have repeatedly stated, at least not in classical sense of a programming error. I do not even know what sort of error I could make that would cause such behavior. Do you? I am more inclined to think that I am running into some Access oddity that is not being correctly handled by the internal machinery, like maybe if a dialog form is called from a subform during an active built-in event, or some such weird combination of circumstances that was overlooked by Microsoft during testing.

I have also spent quite some time going over my Access manuals, particularly Getz, Litwin and Gilbert. Their treatment of custom events is not as thorough as I would like, which is also one of the reasons it took me so long to get started using them. Nonetheless, what they write is much more in line with what I am doing than what you have written here. Specifically, they use phrases like "you raise a useful event in your subroutine and then VBA executes any other part of your program that happens to be listening for the event". Note – listening for the EVENT, not for a specific entity raising the event. They also repeatedly stress the independence of sender and listener, and they use the term encapsulation as I have done – isolating actions and data from direct interaction with the outside world.

Nowhere do they even mention your notion of a 'contract' between sender and listener, except in the very limited case of a form wanting to react to a control event firing on a different form. In that case, they do use your approach, because they are interested in when a specific FORM raises a specific event. I am not – I don't care who raises the custom events I am reacting to, and I want specifically to be able to add more entities raising the event WITHOUT having to locate and modify every bit of source code that is supposed to deal with the fallout from that event.

To be fair, they also do not advocate my design of a central event raiser – they just don't go into much detail about such things. I suppose they had to pick and choose quite a lot. Their books are massive even so – the edition I have contains over 2600 pages. The central class module was purely my own invention, after a great deal of hunting around the net and lots of failed experiments. Again, if you know of a better way to achieve my goal than what I have constructed, I would be happy to hear it. I tried many ways to use the RaiseEvent command directly from the place where the action was taking place, but never managed to make it work. I agree, having to go to a central class module is a little awkward. I would love to be able to just say RaiseEvent "Table X has just added a new record" and have anybody that cares be able to hear that, without the additional ballast of a class module intermediary. I do not know how to do that, and my reading and experiments seem to indicate that it is not possible. If it is and you know how, I would be grateful for some direction.
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 09:01
Joined
May 21, 2018
Messages
8,525
I actually have read Litwin and Getz desktop developer handbook manuals cover to cover, and I can assure you my understanding of events and proper construction of events is in the same line with them. Same as in every other event driven language I know. You seem to stubborn to listen to what I am saying. You seem to put words in my mouth for things I have not said. If you can find me an example of a class that traps an event without a reference to that object raising the event I will be proven wrong. But you cannot.
In your "centralized event raiser", no magic is happening. No class is just listening to events. Every class that is listening for an event has a pointer to an instance of the centralized event raiser. The only difference is that you have one place (single instantiated class) that raises the events.

Private WithEvents ExtTableChange As cls_ChangeEvents

You have one Instantiation of cls_ChangeEvents and everyone listening for these events has a reference to this instantiations.

For what you want to do this is probably the best that can be done in vba. I just do not know how much real world utility there is. As I said, I have seen this done in M&S. This is not some generic implementation of event driven design, this is a unique implementation.

You mention that this "centralized event raiser" concept you have seen as the standard way of doing event driven programming.
I only wrote that what I have seen from many other sources, including manuals from people I know to be knowledgeable state that separation of the sort I describe is the proper way to do such things.
Can you pass any references or links? Like I said what you are constructing is a niche design, not something I ever seen described as the standard for program flow.
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 08:01
Joined
Feb 28, 2001
Messages
27,140
There are only two things I know of that will easily cause this problem. One is a "confused" event sequence. The other is a scoping / qualifying issue where something is NOT in scope unless you make that reference you mention. MajP perhaps didn't like the "confused event sequence" idea, but I think he would also agree that the behavior in question seems to be scope-related. It might be tough to figure out which item is not in proper scope, but that would surely have the described effect of needing a reference to make it work.
 

Petr Danes

Registered User.
Local time
Today, 15:01
Joined
Aug 4, 2010
Messages
150
I actually have read Litwin and Getz desktop developer handbook manuals cover to cover, and I can assure you my understanding of events and proper construction of events is in the same line with them.
I suppose you can assure me, but I don't see it. Specifically, I don't see it in G, L & G manuals, except in the one case that I mentioned, of a form reacting to control events on another form.

You seem to stubborn to listen to what I am saying.
No, I'm not too stubborn to listen – I have listened, very carefully. But you keep repeating your own way of a tight coupling between sender and listener, and I keep telling you, that is not what I want, and also not what I think is the proper way to handle such things. Things do not generally work that way in the outside world, either, and I think event-driven programming is an attempt to emulate that. Your way is the equivalent of having specific responders to specific people doing specific things, rather than just the things happening. It would be like having a fire department that had to know the person setting a fire, and having a specific response team for every person that could set a fire. If a new arsonist came along, the existing fire department could not respond, because they would not be set up for that person. A new arsonist would require a new fire department, and that new department could not respond to any of the old arsonists' activities. It would be a completely ridiculous design, and I think having such a specific and limited event responder in program code is also poor design.

You seem to put words in my mouth for things I have not said.
I do not know what words you think I have put into your mouth. You have said I have an error in my code, and you have used specifically the word 'contract'. I have responded to that.

If you can find me an example of a class that traps an event without a reference to that object raising the event I will be proven wrong. But you cannot.
There are a great many event-driven languages, and I do not know anywhere near all of them, but there are constructs that do not carry information on the originator of the activity. Probably error trapping is the most obvious. When a bit of code throws an error, it does not carry information on which module or which line of code generated the error. That is an event, and you have to add special code to discover the author. Yes, I know, error trapping in VBA is confined to the module in which the error happens, but if you don't specifically trap it, the error bubbles back up through subroutine calls with no information on who caused it.

In your "centralized event raiser", no magic is happening.
Now you are putting words in my mouth. I have never made a claim of some sort of magic, only isolation of the code generating an event from the code handling the consequences. Since I cannot do it as directly as I want, this is what I came up with, and it DOES do that.

I just do not know how much real world utility there is.
Well, you have one example before you. And I do not doubt there are others. It seems painfully obvious to me that there are numerous instances where nobody cares who did something, only that it happened.

As I said, I have seen this done in M&S.
I do not know what M&S is.

You mention that this "centralized event raiser" concept you have seen as the standard way of doing event driven programming.
No, that is NOT what I wrote. In fact, I specifically wrote, just yesterday, that it was my own invention, after I couldn't get anything else to work properly. There may be a language that does what you challenge me to produce, but I do not know of one personally. However, my ignorance on a subject is not proof of its non-existence.

Can you pass any references or links? Like I said what you are constructing is a niche design, not something I ever seen described as the standard for program flow.
One reference is the one I already mentioned: Getz, Litwin and Gilbert. But since you claim that they support your view of things, when I do not see it that way, I suspect that would be the fate of anything else I dredge up, and so my effort in that direction would be a waste of time.
 

Petr Danes

Registered User.
Local time
Today, 15:01
Joined
Aug 4, 2010
Messages
150
There are only two things I know of that will easily cause this problem. One is a "confused" event sequence. The other is a scoping / qualifying issue where something is NOT in scope unless you make that reference you mention. MajP perhaps didn't like the "confused event sequence" idea, but I think he would also agree that the behavior in question seems to be scope-related. It might be tough to figure out which item is not in proper scope, but that would surely have the described effect of needing a reference to make it work.
Scoping is something that I know only superficially. But you may be right. I did not want to take a chainsaw to my DB to find the source of the problem, but it seems I may have to, if only to quiet the hornet's nest I have stirred up here.
 

Petr Danes

Registered User.
Local time
Today, 15:01
Joined
Aug 4, 2010
Messages
150
Can you pass any references or links? Like I said what you are constructing is a niche design, not something I ever seen described as the standard for program flow.
I can give you one positive reference to the topic in general. My central point concept avoids the problem of combinatorial explosion, which yours suffers from. Multiple event raisers and bound event handlers very quickly becomes unwieldy. https://en.wikipedia.org/wiki/Combinatorial_explosion#Computing
 

pdanes

Registered User.
Local time
Today, 06:01
Joined
Apr 12, 2011
Messages
70
Can you pass any references or links? Like I said what you are constructing is a niche design, not something I ever seen described as the standard for program flow.
A ways down the road now, but for the sake of completeness in the archives...

I ran across this just recently: https://nolongerset.com/raising-custom-events-in-vba/

The author writes his tutorial much more in line with my understanding of how events are supposed to work, Specifically, he states:

"Remember, RaiseEvent is nothing more than an announcement. Whether anyone is listening is an entirely separate matter."

and

"I said earlier that each time we call RaiseEvent, we can never be sure how much other code we might be kicking off. This is another one of the differences between purely procedural code and event-driven code. With event-driven code, we can have multiple listeners handling the same event."

This is exactly how I envision events working - someone doing something announces it to the world, caring nothing for who might be listening, and someone interested in specific fallout listens for that happening, caring nothing for who did it.

I do not claim that your way of creating specific 'contracts' between sender and listener is necessarily wrong. It is obviously working for you, so fine. And I'm sure there are circumstances where it will work for other people.

But I do not think that such tight coupling in source code is the intent of event-driven design. Having to change source code in every possible listener when a broadcaster changes, or every possible broadcaster when a listener changes is anathema to everything I know about code encapsulation, which is now considered standard best practice.

https://en.wikipedia.org/wiki/Encapsulation_(computer_programming)
 

gemma-the-husky

Super Moderator
Staff member
Local time
Today, 14:01
Joined
Sep 12, 2006
Messages
15,638
Main form has a subform with some associated records. In the main form's OnCurrent event, I call a public routine in the main form's code that does some display housekeeping around the subform's contents. All has worked well for years.

I am struggling with this. The point about a subform is that it is self contained, other than the link to the container/main form. I struggle to see what you would be doing IN the subform that needs any involvement or knowledge from within the container form, or vice versa.

And I now realise that this is an old thread....
 

Users who are viewing this thread

Top Bottom