Is it possible to raise built-in MS Access form events programmatically? I have a
feeling it isn't but thought I would check. (I am using Access 2003).
For instance, I want to do something like this within a private sub on the
form:
RaiseEvent Delete(Cancel)
and have it trigger the Access.Form delete event -- i.e. without actually
deleting a bound record.
Note my delete event is not handled by the form itself but by an external
class, so I can't simply call Form_Delete(Cancel).
I can understand your confusion -- I didn't explain any of the bigger context. Sorry.
Basically, the situation is I have an 'index' i.e. 'continuous-forms' form which is bound to a read-only query. The query has to be read only because it involves an outer join. But, I want to be able to delete underlying records from this form.
So my first thought was to do the deletion outside the form recordset, eg. using a delete query. And I was hoping to hook the standard Delete/BeforeDelConfirm/AfterDelConfirm events around this manual deletion routine by raising these events myself. But alas, this is not possible.
If the form itself handled these events, I could simply call the handlers (Form_Delete, etc), but my project has custom classes that handle form delete and update events (validation, confirmation, logging, etc.) for all the forms. (#Smandoli, it's not well-documented, I just discovered it a few months ago and use it extensively now -- maybe you know about it already -- you can set up external classes to handle your form events. See for example here)
Long story short, I found a workaround I'm satisfied with. It involves making the 'index' form a subform of another form that is bound to a recordset that can be deleted from. So the deletion can be done in the outer form using the standard Access form events, based on the selection in the inner form.
#Knox, I disagree in principle that being able to raise 'built-in' events yourself is difficult to document and maintain. Plenty of other frameworks depend on it. In practice, I agree with you, since we all have to work within the limitations of our tools and 'best practices' that evolve around those limitations. The blessing and curse of Access is its tight binding between recordsets and forms...
In common, there is simply no need to fire standard form events on your own, normally this shows a wrong understanding of form events in general (if not even events in general).
The form events exists to react on user interaction with the form or to notify the code behind of something that generally happens (like the Form_Load event). The event subs are there to react on these event - nothing more.
It is an often seen thing that people wants to execute event subs directly, but that's also a wrong way. There is a reason why event subs are in general declared as "Private" and not "Public", it should prevent calling them directly from outside the code module, but in fact you should also not execute any of them inside the same code module. Event subs always has to be called exclusively by their events, although it's possible to call them directly.
If an event sub has any code which should be executed also elsewhere then create a private or public sub inside the same module (depending on if you want to execute them from outside or not) and then call this sub from the event sub. If you think you must execute the same sub from elsewhere you can now also call the same sub. This is not a question of "it is possible to call the event sub directly", it is mainly a design question. You should always be sure that an event sub was called only by the event itself and never by any code. The problem when calling an event sub by code is that you can get in trouble very fast if you execute a code and also a real event executes it. In the end you get a big chaos of code which is very hard to debug.
It is, by the way, of course possible to call the event subs from a class module which has a reference to the form (which is needed if you use the class module to handle general events). You only would need to declare the event subs as Public and then you can call them with the form reference, but as stated above: Don't do that.
If a class module is used to handle the events then you can do anything here, you don't need the form code.
If a query is read only and you want to delete a record of a base table no event sub could help you. They are fired when the user wants to delete something which he can't do because it's read only so DoCmd does also not help you.
Like David said in the comment above, simply create a Delete button anywhere you want which can then read out the ID of the current row in the continous form and start a "DELETE" SQL command, then simply requery the continous form and you're done. You can also handle this in your standard class module because you can not only forward form events you can also forward control events on the same way. Create an Init procedure in your class module which takes all the controls from your form you want to handle with it any maybe additional the name of the base table in each continous form, then the class module can assign it to a standard "WithEvents" defined control variable of for example type CommandButton and save the base table name to a string variable. (Don't forget to set the OnClick event to "[Event Procedure]" in the Init procedure.)
In the Load event of your continous form where you probably initialize your class module you can then forward the base table name and the delete button control to the Init procedure of the class module which then can handle the deletion on a very generic way by starting a DELETE query on the base table and requery the form because it already has the form reference also. No need to call any event procedure.
Last but not least: Maybe there are frameworks which allow you to raise events directly but in common I would say that the creators of such frameworks also didn't understand the purpose of event procedures. If you have ever created an own event in a class module of your own you will see that they also cannot be raised outside the class module. Of course, you CAN create a "RaiseEvent" sub on your own to call them externally - and in fact, in case of own events it can make sense in some scenarios. In case of form (control...) events they should inform the code about something happened and there should be a reaction now. If you use events in own class modules you would normally also create a "WithEvents" variable in the outside module to get informed when an event happened in the other class module. An event should make it possible to make the module objects independent of each other. The module with the event will only raise the event and it doesn't know if anyone is listening to it or react on this event. It informs "the world" that there was something which happened in the class module, nothing else. Like a radio station which sends the daily news "to the world" but it doesn't know about if anyone listens to it. Normally, no listener of the radio station would go to the radio station and reads his own news for other listeners. Only the people at the radio station decides what to send and when. Same story.
Related
I have an event class which extends the normal events class so I can pass parameters and have custom events.
I have a message event which I use to display a message to the user, I send an event to trigger this message from many places in my project.
I now need to give the user an option in this message and access the answer in the original class which sent the event that triggered the message.
My solution is to pass a function as a parameter to the event listener, then on click the function in my original class is called.
Is this a good approach?
My other solution was to create more events to handle the various options, but I may end up with many types of events.
This is not a traditional delegation of concern. If the original class cares about an event, it should listen for it and react to it. If you wanted to extend "event" it would traditionally be to have it carry more data (or more descriptive data), not to have it carry a function closure.
Intro:
I have two separate forms.
frmABC
frmXYZ
I have frmABC in focus and I run a procedure that will "Tick" a checkbox called ChkConfirmed on frmXYZ.
Question:
What is the difference between these two ways of referencing another form?
1. Form_frmXYZ.ChkConfirmed = True
2. Forms!frmXYZ.ChkConfirmed = True
For some reason, only #2 works in this scenario. For me this is bewildering purely beacuse I have always used #1 and it has never complained before (when I say complain, I mean it does the job).
But, when I use #1 here and step through the code, it definitely runs the code but does not check any boxes...just nothing.
So, I would love to know the technical differences to help me understand when to use each one and in what cases.
EDIT:
Actual code snippet (as requested)
#1 Version
#2 Version
Access (I think >=97) treats Forms as a Class which means your forms are now a class module and can have all [class behaviors] including instancing.
Form_your_formname: you are referencing the Form via the Class module.
Forms!your_form name: You are referencing the form by its form name.
To access a form via Forms!form_name, the form must already have been loaded. Otherwise the form won't be reachable and you will get an error message "the referenced ...... not found"
On the other hand, Form_form_name can be accessed at any time as a class. It can have multiple instances like all classes do. Accessing an unopened form via its class module will cause the form is being instanced. This means Access will create a new hidden instance of that Form.
To test this try following.
Create a new form called: frm_test with a text box in it called: txt_id
go to your immediate window and try following code:
Edit forgot to mention. The test form hast to have a vba module attached to it then only it becomes a class module
Form_frm_test.txt_id = 1
Form_frm_test.visible = true
?Form_frm_test.hwnd
docmd.openform "frm_test"
?Forms!frm_test.hwnd
Now you will see two instance of the frm_test form and each of them will have their own window handle.
to answer your question:
But, when I use #1 here and step through the code, it definitely runs the code but does not check any boxes...just nothing.
its because your form is being instanced and its hidden.
So, I would love to know the technical differences to help me understand when to use each one and in what cases.
Technical explanation given above.
if your form is already loaded you can use the Form!form_name / form_name to access it. If you are instancing use the class name.
To be honest, I've never seen your 1st example used, ever... In fact a quick test in Access 2010 fails with an "Object Required" error message. All the code I've ever done uses the exclamation, which (someone correct me if I'm worng) works in all circumstances where you would need to reference another form for something.
I'm new to programming and I've been checking a lot of game coding tutorials. I've noticed that on most of them they use custom events to trigger methods instead of calling a method directly.
What's the reasoning behind this practice? Why aren't they just calling the method?
For example:
We have two objects: A and B. A has method A.methodA() that B needs to use when X condition is triggered.
Why implement:
B dispatches an event to A that tells A to run A.methodA()
Instead of:
B uses A.methodA()
The main reason is separation of interests. When using events, class A doesn't need to know about the existence of class B (and vice versa).
Some benefits to this are:
Much easier unit testing (you can test Class A without class B)
Less chance of breaking your code when you change class A or B
Less references to other classes in your code, which reduces the potential for memory leaks
Cleaner code
More flexible/reusable code (a bunch of other classes could all listen/respond to the event without any additional code in the your dispatcher)
Typically in bigger applications using events will help abstract everything. When you have 15+ classes and they're all ditpatching events to a controller, it's a lot easier to figure out what's going on than reading through all different parts of the code to trace functions. Using callbacks begins to create spaghetti code.
However, direct function calls are going to be executed faster than events.
Personally, I use custom events simply for the ease of use. I can have one class dispatch an event when something happens (say an animation finishes or an error occurs in a download) and any number of other classes run any number of other functions based on that event. In addition, I code for reusability. The goal of each class is complete independence so that it can run in any project without needing other packages. So rather than have one class call a method of another class, I dispatch an event from the first class that the second class listens for and then run that method. Then when I need that first class for another project, I can just copy/paste it without having to modify it and without losing any functionality.
EDIT:
Also, it's worth noting that sometimes people do what you describe to get around having to pass in event arguments.
Say you have a button on the stage and you need to be able to click it, but you also need to be able to manually call that method. Some people don't realize you can pass in a null event and have only the single method. Or you can set it as a null default argument, see below:
private function onClickHandler( e:MouseEvent = null ):void{
//as long as you never reference "e" within this method, this method can be used both for MouseEvent listeners and manually calling it elsewhere in the code
}
That technique can help avoid having an event handler that only calls another method and nothing else. At this point in my programming, every single AS3 event handler I write sets the event argument to null by default. It just makes things easier later on.
You might want to read this.
And also note using the callback method allows you to pass parameters to it directly and not via a custom event model.
I built my own, very simplified, events dispatcher system. AS Event model is very powerful, but in 99% of situations you don't need that power. A simple callback with parameters fired as an event is more than enough. You can still retain the versatility from an event model, but don't need to write too many lines of code for, let's say, a simple button.
I can setup a simple event like this:
Buttonizer.autoButton(_buttQuit, this, "onPress");
public function onPressQuit(c:Sprite) {
// Execution goes here
}
You can build your own event model, it will make life simpler, and your code much more concise.
First off, I've done a lot of research on the web (including this site) and have found lots of conflicting information on how the model and controller communicate in an MVC pattern. Here is my specific question (I'm using AS3), but it's a general MVC question...
I have two main components... a list of recipes and a form that displays a selected recipe. The form has an edit state that allows you to edit the recipe and then save or cancel the changes. What is the best way (using MVC principles) to handle changes made to a recipe? So far, I have the save button trigger an event which is captured by the controller.
Should I have the save button (the view) pass an object with the current state of the fields along with the event (some logic in view)? Should I allow the controller to hold access to the view and have the controller figure out what's in the fields on its own (added coupling)? Should events be made every time a field in the form is changed and the controller keeps track of the state of each field (lots of events)? Or is their another way? Note: I don't want to bind the fields to the model because I only want the data to save if the save button is clicked.
Any help would be greatly appreciated. Thanks!
Should I have the save button (the view) pass an object with the
current state of the fields along with the event (some logic in view)?
yes, this is not 'logic in the view', it does not decide anything, simply reporting an action and its current state
Should I allow the controller to hold access to the view and have the
controller figure out what's in the fields on its own (added
coupling)?
no, this would become very messy, pass a VO with the event
Should events be made every time a field in the form is changed and
the controller keeps track of the state of each field (lots of
events)?
is an option, but this basically is the same as hitting the save button, the trigger is different (TextField.onChange), but you can dispatch the same event (setup is form = view, dispatches one general event with a VO, not an event for each field)
Or is their another way?
MVC flow w/ events:
onClick save btn: a RecipeEvent.SAVE is dispatched (from the view), with a VO (value object) containing the Recipe data (e.g. RecipeVO)
the controller catches this, and as the controller is where the logic resides, it decides what to do with it: update the RecipesModel (either directly by calling a method on the model, or by a custom event e.g. RecipeModelEvent.SAVE)
the model stores the data, and dispatches the RecipeEvent.UPDATE event (with the RecipeVO)
the views updated itself accordingly (check if the RecipeVO.ID is same, update data representation e.g. title…)
optionally, a controller could save the data to a back-end/remote database
As for the event listeners: views listen to the model, controller listen to the views.
About de-coupling:
use interfaces (by using an IModel you can swap out the model easily by another implementation, as you register the event listeners against the interface instead of the actual implementation)
Obviously, all this results in a lot of registering/removing event listeners, and keeping reference to the models/views/controllers to be able to register to the appropriate instance. An alternative is to use a framework as RobotLegs, as it makes a central event-bus available + easy/automatic cleanup of event listeners in the mediator class of a view.
I think this is really a database question. what I would do is create a stored procedure that first checks to see if the recipe already exists. If yes then update it. If not then add a new recipe. (you'll have to bind your entity to a stored procedure. other MVC frameworks can do this. I don't know about actionscript)
if that's not an option then I guess you would have to cache the original form in a helper class in the controller and then compare it to what the user is trying to save. And have the controller decide whether to update the recipe.
I think it's much cleaner to use the first way, but I've never used actionscript so...
Colin Moock's lecture on MVC in ActionScript is quite old, but still one of the best explications: http://www.moock.org/lectures/mvc/
Your model should populate your view, and your view should send input events to the controller, which should decide what to do with the input. As g10 says, wait until the save button is clicked and then pass an object with the modified fields up to the controller for processing. The controller can then decide whether or not to accept it, and whether to update an existing model object or create a new one.
I have a public function in an Access form
Public Function PopupProcess() as long
MsgBox Me.ActiveControl
PopupProcess = 1
End Function
When I call
eval("forms('MyForm').popupprocess")
it shows a message box 2 times. Does anybody know why it does that?
I Have Access 2003 with SP3.
EDIT : Main idea is to call function from that form for Custom Commandbar control OnAction.
Maybe you have better way to call function from a form for commandbar control.
This is a very long standing bug that’s been around since the days of access 97, (about 4-5 versions of access).
The solution here is to NEVER use the forms qualifier, simply place the following in your on action event, and you’ll be just fine
=PopUpProcess()
Note that you must precede it with=, and the suffix must have the brackets ()
Keep in mind that you can actually use behavior to your advantage. The function that runs is going to be from the form that currently has the focus on the screen. That means you can have different forms with the same name of the function, and whichever form has the focus, that function with that name will run from that forms code module.
Even better, if one of the forms does not have that function as public in the forms code module, then the function in a standard code module is used. So you might have nine forms, that all use the standard one function in the main standard code module. However, the 10th form might need to run special code, so you simply place that function code in the form’s code module as public and it will run in place of the public on in the standard code module.
This approach allows you to build a single custom menu bar that applies to many different forms, but those many forms will run different code on from that custom menu bar. This also encourages you to place the menu code in the form it belongs.
So to solve your problem, simply don’t use a form’s qualifier, and use the above format.
Note that you can pass Parameters from those functions also, for example
=PopUpProcess(‘hello’)
And then declare the function as:
Public Function PopUpProcess(strParm as string)
Keep in mind that the function and syntax and all of what I stated above also applies to when you use the on action in a ribbon for access 2007.
No idea. What happens if you call it like this?
Call Forms("MyForm").PopupProcess
Try using the CallByName function, instead of eval, to call your function. It should only fire your function once, and it will still allow you to parameterize the form name and the function or sub name:
CallByName Forms("MyForm"), "PopupProcess", VbMethod