add click event on dynamically created child menu items - vb.net

How can you add a click event to dynamically created menu item?
I thought I could do something like
Loop through all the items in the Menu1.DropDownItems then create a mousedown even on the item and execute an action based off that.
I'm new to VB and was wondering what logic to use. Will that even work? How will the events be saved through the life of the application?

You will have to have a method that fits the event's signature. Then, when creating the MenuItem, you can add a handler to the event:
Dim item As New MenuItem(...)
'...
AddHandler item.Click, AddressOf myEventHandler
Sub myEventHandler(sender As Object, e As System.EventArgs)
'Do something
End Sub
You cannot create an event in a class that you don't have access to. The only option would be to derive from it, but this works only in some cases. In case of the MenuItem, this is not even necessary, because it already provides a Click event. You just have to add a handler for it. The handler is saved in the item's event, which maintains a kind of list of handlers.

Related

vb winform custom event handler

I am trying to add custom event handler on user control.
if I create user control on the same solution and on the same project, I can add custom event handler on the main form.
AddHandler usercontrol1.button.click, addressof button_clickHandler
when I type in usercontrol1. I can select button from the pop-up code completion
but if I create another project for user control on the same solution, say user control called uc
so after I place it on the main form with name uc1
AddHandler uc1.button.click...
when I type in uc1. I can't see button on the pop-up code completion and when I compile it if I type in
AddHandler uc1.button.click, addressof button_clickHandler2
I get compile error uc1.button is not accessible in this context because it is friend.
does user control custom event only work if the user control created on the same project?
I am thinking just to separate common user control and other common library, in one project, so it can consume by other project, instead of creating the same user control on each project.
I appreciated if you could give some pointer on how to create custom event handler or I just have create user control on the same project to get it to work.
Thank you.
While the simple solution is to just declare the child control(s) Public instead of the default Friend, good practice would be to not expose child controls of a user control anyway, no matter where it's declared. Child controls should be made Private and you should provide pass-throughs for any properties, methods or events you wish to access from the outside. For instance, declare your own ButtonClick event in the user control, handle the Click event of the Button internally and then raise your own event, e.g.
Public Event ButtonClick As EventHandler
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
OnButtonClick(EventArgs.Empty)
End Sub
Protected Overridable Sub OnButtonClick(e As EventArgs)
RaiseEvent ButtonClick(Me, e)
End Sub
Your form will then handle events of the user control and not its child controls. See here for more information about declaring and raising your own events.
BTW, a reason not to make child controls Public is that then any code that has access to the user control has access to EVERY aspect of the child controls, including being able to replace them with new controls. By making them Private and providing pass-throughs, you expose only the specific aspects of the child controls that should be accessible from the outside. It also means that your user control behaves more as an integrated unit, rather than a collection of parts. On the matter of events specifically, it also means that the user control is the sender in each event handler, rather than the individual child control.

Keep track of Window being Last Focus

The VB.Net program I am creating dynamically created Panels within a TableLayoutPanel and adds form elements to them. I need to keep track of what the last of these Panels to have focus was, and am hitting a bit of a brick wall.
I have tried creating an event class for when the Panel has focus:
Private Sub Self_GotFocus(ByVal sender As Object, ByVal e As EventArgs) Handles Me.GotFocus
GlobalController.Focus_Target = Me.Name
End Sub
The classes for each Panel Inherit from Windows.Forms.FlowLayoutPanel, which I why I have the call being Me.GotFocus. Additionally, the GlobalController class is just a class meant to hold global variables for the program.
Now the issue I am having, is that this event only seems to trigger when I actually am deleting the panel. When the panel is created, if I click on it, or any of it's form elements, the event never gets triggered (I debugged the program with a breakpoint).
I can't exactly figure out why this only triggers when I go to delete the panel, and not at any other time. Is there another event I should be using instead of GotFocus?
Use .Enter event in your panel since GotFocus is related only to focused control (not it's parent), mostly when UICues is set.
See MSDN GotFocus

How to have a user control within MainForm call the MainForm Objects?

I have a user control that I created with certain buttons, and I placed it within the main form, which already contains things like buttons and panels. I want to control(send messages) to these fields when I press the buttons in the user control, but I can't figure out the OOP implementation required to achieve this.
I was advised to create an Initialize(f as Mainform) in the user control code in order to keep an explicit reference to the main form, but I have not been able to control the fields of the main form.
How can this be achieved? I am using visual basic, btw.
Declare an event in the user control, and then write a handler for that event in the form.
In the control:
Event Zoomed()
In the control, to raise the event (call the handler):
RaiseEvent Zoomed()
and add the handler to the form:
Sub aview_zoomed() Handles aView.Zoomed
...
End Sub

Where should controller-like code be written in my vb.net app?

I am refactoring an existing project that is one large file. All form controls live in a single form, and all event handlers live in the form's code behind.
I am refactoring out a piece of the UI into a User Control. One piece of this UI is an 'Add Contract' button. This goes to my data layer, adds a row to a DataTable, and various grids in other parts of form are updated with the new row.
My question is, where should I put the event handler for the button click in the User Control?
I could leave the event handler code in the parent form, and use AddHandler in the User Control to reference the parent form's sub
I could write all the event handler code in the User Control. In this case, I'd need to access the parent form to get a reference to the data layer.
I come from a web background where I'm used to the 'controller' handling this sort of thing. I suppose my parent form is turning into a kind of controller - but is this a good practice? Should I have a separate class that coordinates user interactions with my model layer, or, once I separate out all the UI into separate user controls, will the main form be a good place for this sort of thing?
Your user control should raise events that the form hosting the user control will handle. If the user control has a reference to the form, then the user control is not reusable in any other context; in other words, the user control is tightly coupled to that one form and form X would break if it tried to use the user control.
Note: If your form is the only thing that will use the user control, then there is not much re-usability value in making it a user control at all. Kind of similar to it is not much use to make an interface if there is only one implementation of said interface. That said from an organization standpoint, user controls can be used to clean up a crowded form. It also has the benefit of allowing for the dynamic loading of content in user controls.
There is nothing wrong with your parent form becoming the controller.
Here is a quick example (in this case the clicking of the button in the user control) of how you can raise events from your user control and subscribe to the event in the form:
Public Class UserControlClass
' Define event that will be raised by user control to anyone interested in handling the event
Public Event UC_Button1Click()
' Mechanism to allow event to be raised by user control
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
RaiseEvent UC_Button1Click()
End Sub
End Class
Now in your form class, you need to add a handler for the event raised by the user control, like this:
AddHandler userControl1.UC_Button1Click, AddressOf Button1_Click
Finally, you would create the method that is referenced in the AddressOf syntax, like this:
Public Sub Button1_Click(ByVal sender As Object, ByVal args As EventArgs)
' Do something here
End Sub

Access event in a user control created in code behind?

I'm trying to create a user control in my code behind, and then respond to events in that control. Presumably because the control doesn't exist at compile time, Visual Studio can't compile the handler subroutine I created to catch my control's event. Importantly, I want to decide the type of control at runtime (which is why I'm not just hard-coding it).
[before going on, the controls work correctly, including events and event handlers when used in the 'normal' way of creating the controls in XAML. I want to create the control instances in code behind so I can avoid duplicating pages that are 99% identical]
This 'works' (but doesn't give me the flexibility I need):
Public WithEvents AnswerPanel As MyControls.ScrollerControl
... (and the initialisation in the New() sub):
AnswerPanel = New MyControls.ScrollerControl
ItemStack3.Children.Add(AnswerPanel)
AddHandler AnswerPanel.GuessMade, AddressOf CheckAnswer
... (this is the handler sub responding to a custom event in the ScrollerControl)
Public Sub CheckAnswer(answer As String) Handles AnswerPanel.GuessMade
With the code above everything works as I expect: the control is created at runtime and its event is handled correctly.
What I want to achieve is to be able to choose a different user control when I initialise my control (e.g. ScrollerControl2, ScrollerControl3, etc.) I can create the controls this way by changing the first line to:
Public WithEvents AnswerPanel As UserControl
But once that change is made I can no longer reference the custom event in my handler as (presumably) the compiler sees it as a generic UserControl, which doesn't include my custom GuessMade event. The compiler errors on the event name and tells me it doesn't exist.
I'm sure I'm doing something wrong here. I think it's a theory/concept issue rather than my code.
Am I on the right track or going about this in the wrong way?
If I am reading this right, you have a user control that fires an event and you want the parent page to catch that even? If so, you need to raise the event, which will cause the event to bubble to the the parent. IE:
Partial Class user_controls_myControl
Inherits System.Web.UI.UserControl
Public Event DataChange As EventHandler
End Class
This creates a control with a public event called DataChange. Now, if you look at the code in the parent page that instantiates the user control, you will see that it has an event called "OnDataChange". Just like an onCLick event, you can assign this a method in the parent page. Now, you just need to raise the event in the user control. This can be added in some event in the control, like a button click or radio button change event:
RaiseEvent DataChange(Me, New EventArgs)
This takes two objects, the sender and event arguments. Typically I pass ME, which is the user control. This is great because you can use reflection to get all the controls public properties. You can also use this to cast objects to your control type. I rarely pass event arguments but you certainly could.
I answered a similar question here: Handling events of usercontrols within listview
If this is not what you had in mind, let me know
EDIT: To add a user control dynamically and attach the event:
First, in the page that will be using the control, you will need to add a place holder:
<asp:PlaceHolder ID="placeholder1" runat="server"></asp:PlaceHolder>
as well as a reference to the user control at the head of the page (depending on how the page is setup, you may not need this. If you get a page directive error, remove it):
<%# Reference="" Control="~/user_controls/myControl.ascx"%>
In the parent page, you can then create a user control and add it to the place holder. You must declare the user control with events like this:
Private WithEvents myNewControl As New user_controls_myControl
then, in some method you can add it to the page like this:
Dim getPh As New PlaceHolder
'create an instance of the user control
newMyControl = CType(LoadControl("~/user_controls/myControl.ascx"), user_controls_myControl)
'get a handle on the place holder
getPh = me.placeHolder1
'add the user control to the place holder
getPh.Controls.Add(newMyControl)
Then, make sure you have event method:
Protected Sub myEvent(ByVal sender As Object, ByVal e As EventArgs) Handles myNewControl.DataChange
End Sub
So, if you added the RaiseEvent to the user control like I suggested earlier, this should work for you.
I have an answer to this now. As I suspected I was sort of thinking about the problem from the wrong angle.
In a nutshell I was trying to raise an event from my user controls, but I needed to be raising the events in the base class and calling that from my user controls.
So my base class (which my user controls inherit from), now contains the following:
Public Event GuessMade(answer As String)
Protected Sub RaiseGuessEvent(answer As String)
RaiseEvent GuessMade(answer)
End Sub
Then, in my user control(s), when I need to raise the event, I simply call the RaiseGuessEvent sub like this:
Me.RaiseGuessEvent(CurrentValue)
And additionally, I had to remove the event from my subclasses/user controls, of course.