0
votes

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?

2
You absolutely do need to include here. You can subscribe to events from code behind. Your issue is that you have code that won't compile, without being able to see that code there's no way to help.Matt Lacey
please update your question to include the additional information in a readable manner.Matt Lacey
I've made some progress with this by creating a "MyControl" class that inherits UserControl and then making my other controls inherit MyControl. I have the event in MyControl and shadowed in my other controls, and everything compiles fine...but the event (which I can confirm is firing) is not detected in the page's event handler. Any ideas?pumpkinszwan

2 Answers

1
votes

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.

0
votes

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.