【问题标题】:Access event in a user control created in code behind?在后面的代码中创建的用户控件中的访问事件?
【发布时间】:2013-03-25 14:06:27
【问题描述】:

我试图在后面的代码中创建一个用户控件,然后响应该控件中的事件。大概是因为该控件在编译时不存在,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 事件。事件名称上的编译器错误并告诉我它不存在。

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

我是走在正确的轨道上还是走错了路?

【问题讨论】:

  • 你绝对需要包括在这里。您可以从后面的代码订阅事件。您的问题是您的代码无法编译,而无法看到该代码就无法提供帮助。
  • 请更新您的问题,以可读的方式包含附加信息。
  • 我在这方面取得了一些进展,方法是创建一个继承 UserControl 的“MyControl”类,然后让我的其他控件继承 MyControl。我在 MyControl 中有该事件并在我的其他控件中隐藏,并且一切都可以正常编译...但是在页面的事件处理程序中未检测到该事件(我可以确认正在触发)。有什么想法吗?

标签: vb.net windows-phone-7 xaml user-controls


【解决方案1】:

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

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 添加到用户控件,这应该适合您。

【讨论】:

  • 杰森,感谢您的帮助。我在设置和触发我的事件时没有任何困难。问题是当我在事件后面的代码中创建我的控件时,没有被捕获。如果我只是在 XAML 中添加我的控件,一切都会完美运行,但我希望能够在运行时选择特定的用户控件,所以我首先声明为基类,然后初始化为继承基类的特定控件.我可以触发事件,但事件处理程序不会在页面上执行(这只发生在我在后面的代码中创建的控件中)。
  • 澄清问题...在我的页面上,如果我这样声明Public WithEvents AnswerPanel3 As MyUserControl,然后在我的构造函数AnswerPanel3 = New AppName.MyUserControl...一切正常。如果我用Public WithEvents AnswerPanel3 As MyBaseUserControlClass 替换第一行(它允许我选择几个类似的用户控件之一)......我的页面不再“看到”事件(但我可以看到用户控件确实触发了事件)。
  • 我编辑了我的回复,以展示我通常如何在运行时创建用户控件并确保事件正常工作。
  • Jason,您添加的代码并没有解决问题:只有当我在页面顶部将控件声明为我的泛型类,然后将其初始化为我的特定控件之一(从泛型类继承)我遇到问题。我需要能够在运行时选择几个不同的特定控件之一。我可以添加零问题的已知类型的用户控件(例如,事件被完美捕获),但这并没有提供我正在寻找的功能。
【解决方案2】:

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

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

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

    Public Event GuessMade(answer As String)

    Protected Sub RaiseGuessEvent(answer As String)

         RaiseEvent GuessMade(answer)

    End Sub

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

     Me.RaiseGuessEvent(CurrentValue)

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-17
    • 2015-02-15
    • 1970-01-01
    • 2011-03-11
    相关资源
    最近更新 更多