0

我试图在后面的代码中创建一个用户控件,然后响应该控件中的事件。大概是因为在编译时控件不存在,Visual Studio 无法编译我创建的用于捕获控件事件的处理程序子例程。重要的是,我想在运行时决定控件的类型(这就是为什么我不只是对其进行硬编码)。

[在继续之前,控件正常工作,包括以“正常”方式在 XAML 中创建控件时使用的事件和事件处理程序。我想在后面的代码中创建控件实例,这样我就可以避免复制 99% 相同的页面]

这“有效”(但没有给我所需的灵活性):

        Public WithEvents AnswerPanel As MyControls.ScrollerControl

...(以及 New() 子中的初始化):

        AnswerPanel = New MyControls.ScrollerControl
        ItemStack3.Children.Add(AnswerPanel)

        AddHandler AnswerPanel.GuessMade, AddressOf CheckAnswer

...(这是响应 ScrollerControl 中的自定义事件的处理程序子)

        Public Sub CheckAnswer(answer As String) Handles AnswerPanel.GuessMade

使用上面的代码,一切都按我的预期工作:控件是在运行时创建的,并且它的事件得到了正确处理。

我想要实现的是能够在初始化控件时选择不同的用户控件(例如 ScrollerControl2、ScrollerControl3 等)。我可以通过将第一行更改为:

        Public WithEvents AnswerPanel As UserControl

但是一旦进行了更改,我就不能再在我的处理程序中引用自定义事件,因为(可能)编译器将其视为通用 UserControl,它不包括我的自定义 GuessMade 事件。事件名称上的编译器错误并告诉我它不存在。

我确定我在这里做错了什么。我认为这是一个理论/概念问题,而不是我的代码。

我是在正确的轨道上还是以错误的方式去做这件事?

4

2 回答 2

1

如果我没看错,您有一个触发事件的用户控件,并且您希望父页面也能捕捉到它?如果是这样,您需要引发事件,这将导致事件冒泡到父级。IE:

Partial Class user_controls_myControl
    Inherits System.Web.UI.UserControl
    Public Event DataChange As EventHandler
End Class

这将创建一个带有名为 DataChange 的公共事件的控件。现在,如果您查看父页面中实例化用户控件的代码,您将看到它有一个名为“OnDataChange”的事件。就像 onCLick 事件一样,您可以在父页面中为其分配一个方法。现在,您只需要在用户控件中引发事件。这可以在控件中的某些事件中添加,例如按钮单击或单选按钮更改事件:

RaiseEvent DataChange(Me, New EventArgs)

这需要两个对象,即发送者和事件参数。通常我会通过 ME,这是用户控件。这很棒,因为您可以使用反射来获取所有控件的公共属性。您还可以使用它来将对象转换为您的控件类型。我很少传递事件参数,但你当然可以。

我在这里回答了一个类似的问题:Handling events of usercontrols within listview

如果这不是您的想法,请告诉我

编辑:动态添加用户控件并附加事件:

首先,在将使用该控件的页面中,您需要添加一个占位符:

<asp:PlaceHolder ID="placeholder1" runat="server"></asp:PlaceHolder>

以及对页面顶部的用户控件的引用(取决于页面的设置方式,您可能不需要它。如果遇到页面指令错误,请将其删除):

<%@ Reference="" Control="~/user_controls/myControl.ascx"%>

在父页面中,您可以创建一个用户控件并将其添加到占位符中。您必须使用如下事件声明用户控件:

Private WithEvents myNewControl As New user_controls_myControl

然后,您可以通过某种方法将其添加到页面中,如下所示:

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)

然后,确保你有事件方法:

Protected Sub myEvent(ByVal sender As Object, ByVal e As EventArgs) Handles myNewControl.DataChange

End Sub

因此,如果您像我之前建议的那样将 RaiseEvent 添加到用户控件,这应该适合您。

于 2013-03-27T13:46:16.847 回答
0

我现在有一个答案。我怀疑我是从错误的角度思考这个问题。

简而言之,我试图从我的用户控件中引发一个事件,但我需要在基类中引发事件并从我的用户控件中调用它。

所以我的基类(我的用户控件继承自)现在包含以下内容:

    Public Event GuessMade(answer As String)

    Protected Sub RaiseGuessEvent(answer As String)

         RaiseEvent GuessMade(answer)

    End Sub

然后,在我的用户控件中,当我需要引发事件时,我只需像这样调用 RaiseGuessEvent 子:

     Me.RaiseGuessEvent(CurrentValue)

此外,当然,我必须从我的子类/用户控件中删除该事件。

于 2013-03-28T00:30:52.117 回答