Asp.net 用户控件负载控制问题

发布于 2024-07-07 14:40:26 字数 1548 浏览 5 评论 0原文

我在使用 LoadControl( type, Params ) 时遇到问题。 让我解释一下...

我有一个超级简单的用户控件(ascx),

<%@ Control Language="C#" AutoEventWireup="True" Inherits="ErrorDisplay" Codebehind="ErrorDisplay.ascx.cs" EnableViewState="false" %>

<asp:Label runat="server" ID="lblTitle" />
<asp:Label runat="server" ID="lblDescription" />

后面带有代码(c#):

public partial class ErrorDisplay : System.Web.UI.UserControl
{

    private Message _ErrorMessage;    

    public ErrorDisplay()
    {
    }

    public ErrorDisplay(Message ErrorMessage)
    {
        _ErrorMessage = ErrorMessage;
    }    

    protected override void OnPreRender(EventArgs e)
    {
        base.OnPreRender(e);

        if (_ErrorMessage != null)
        {
            lblTitle.Text = _ErrorMessage.Message;
            lblDescription.Text = _ErrorMessage.Description;
        }
    }
}

在我的Web应用程序的其他地方,我使用以下代码将用户控件的实例添加到页面:

divValidationIssues.Controls.Add(LoadControl(typeof(ErrorDisplay), new object[] { MessageDetails }));   

我正在使用重载LoadControl 的版本,因为我想将 Message 参数传递给构造函数。 所有这些似乎都可以正常工作。

但是,当在 ErrorDisplay 用户控件上触发 OnPreRender() 时,lblTitle 和 lblDescription 变量都为 null,尽管它们具有等效的标记。 消息变量已正确填充。

谁能解释为什么会发生这种情况?

谢谢

编辑:

为了清楚起见,我还要补充一点,以编程方式将用户控件添加到页面的代码正在响应按钮按下而运行,因此“托管页面”已通过 Init 进行, Page_Load 现在正在处理事件处理程序。

我无法在早期的 ASP 生命周期阶段添加用户控件,因为它们是为了响应按钮单击事件而创建的。

I am having an issue when using LoadControl( type, Params ). Let me explain...

I have a super simple user control (ascx)

<%@ Control Language="C#" AutoEventWireup="True" Inherits="ErrorDisplay" Codebehind="ErrorDisplay.ascx.cs" EnableViewState="false" %>

<asp:Label runat="server" ID="lblTitle" />
<asp:Label runat="server" ID="lblDescription" />

with code ( c# ) behind of:

public partial class ErrorDisplay : System.Web.UI.UserControl
{

    private Message _ErrorMessage;    

    public ErrorDisplay()
    {
    }

    public ErrorDisplay(Message ErrorMessage)
    {
        _ErrorMessage = ErrorMessage;
    }    

    protected override void OnPreRender(EventArgs e)
    {
        base.OnPreRender(e);

        if (_ErrorMessage != null)
        {
            lblTitle.Text = _ErrorMessage.Message;
            lblDescription.Text = _ErrorMessage.Description;
        }
    }
}

Elsewhere in my web application I am adding an instance of the usercontrol to the page using the following code:

divValidationIssues.Controls.Add(LoadControl(typeof(ErrorDisplay), new object[] { MessageDetails }));   

I am using the overloaded version of LoadControl because I want to pass the Message parameter to the constructor. All this appears to work ok.

However, when the OnPreRender() is fired on the ErrorDisplay usercontrol the lblTitle and lblDescription variables are both null, despite them having a markup equivalent. The message variable has been correctly populated.

Can anyone shed any light on why this may be happening?

Thanks

EDIT:

Just for clarity I'll also add that the code which is programatically adding the usercontrol to the page is running in response to a button press, so the 'hosting page' has progressed through Init, Page_Load and is now processing the event handlers.

I cannot add the usercontrols at an earlier asp lifecycle stage as they are being created in response to a button click event.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

说不完的你爱 2024-07-14 14:40:26

我也尝试过以下代码 - 产生相同的结果(即 lblTitle 和 lblDescription 均为空)

protected void Page_Load(object sender, EventArgs e)
{
    if (_ErrorMessage != null)
    {
        lblTitle.Text = _ErrorMessage.Message;
        lblDescription.Text = _ErrorMessage.Description;
    }
}

我了解到 LoadControl 函数将其正在加载的控件带到其所在页面的当前“状态”正在被纳入。 因此,Init、Page_Load 等都作为 LoadControl 调用的一部分运行。

有趣的是,这篇(未答复的)asp.net 论坛帖子展示了与我遇到的相同问题。

MSDN 论坛帖子

另外 - 来自 MSDN:

当您将控件加载到容器控件中时,容器会引发所有添加的控件的事件,直到它赶上当前事件。 然而,添加的控件并没有跟上回发数据处理的速度。 对于要参与回发数据处理(包括验证)的添加控件,必须在 Init 事件中而不是在 Load 事件中添加该控件。

因此 LoadControl 不应该正确初始化控件吗?

编辑:

好的,所以我在这里回答我自己的问题..

我找到了上面链接的论坛帖子的答案版本这里

本质上答案是 LoadControl( type, params ) 无法推断要解析的“page infront”ascx,因此它不会不必费心初始化任何控件。 当您使用 LoadControl( "ascx path" ) 版本时,它会给出前面的页面,因此会执行所有解析和初始化。

所以总而言之,我需要更改初始化控件的代码并将其拆分为单独的部分。 即

Control ErrorCntrl = LoadControl("ErrorDisplay.ascx");
ErrorCntrl.ID = SomeID;
(ErrorCntrl as ErrorDisplay).SetErrorMessage = MessageDetail;
divErrorContainer.Controls.Add(ErrorCntrl);

它应该可以正常工作..它不像我之前的尝试那么整洁,但至少它会起作用。

我仍然愿意接受改进上述内容的建议。

干杯

I have tried the following code as well - which yields the same result (i.e. both lblTitle and lblDescription are null)

protected void Page_Load(object sender, EventArgs e)
{
    if (_ErrorMessage != null)
    {
        lblTitle.Text = _ErrorMessage.Message;
        lblDescription.Text = _ErrorMessage.Description;
    }
}

I had the understanding that the LoadControl function brought the control it is loading up to the current 'state' of the page onto which it is being included on. hence the Init, Page_Load etc are all run as part of the LoadControl call.

Interestingly this (unanswered) asp.net forums post exhibits the same problem as I am experiencing.

MSDN Forums Post

Additionally - From the MSDN:

When you load a control into a container control, the container raises all of the added control's events until it has caught up to the current event. However, the added control does not catch up with postback data processing. For an added control to participate in postback data processing, including validation, the control must be added in the Init event rather than in the Load event.

Therefore shouldn't LoadControl correctly initalise the control?

EDIT:

Ok, so I'm answering my own question here ..

I found an answered version of the forum post I linked to above Here

Essentially the answer is that the LoadControl( type, params ) cannot infer the 'page infront' ascx to parse and hence it doesn't bother initalising any of the controls. When you use the LoadControl( "ascx path" ) version it is given the page infront and hence does all the parsing and initalision.

So in summary I need to change the code which is initalising the control and split it into seperate parts. I.e.

Control ErrorCntrl = LoadControl("ErrorDisplay.ascx");
ErrorCntrl.ID = SomeID;
(ErrorCntrl as ErrorDisplay).SetErrorMessage = MessageDetail;
divErrorContainer.Controls.Add(ErrorCntrl);

And it should work ok.. It isn't as neat as my previous attempt, but at least it will work.

I am still open to suggestions to improve the above.

Cheers

少年亿悲伤 2024-07-14 14:40:26

同意 Mitchel 的观点,您应该能够将 page_load 放入控制代码本身中,该代码将在控件完全可用后触发。

Agreeing with Mitchel, you should be able to put a page_load in the control code itself which would fire after the controls are completely available.

凉月流沐 2024-07-14 14:40:26

好吧,总是添加您自己的加载事件,并在运行构造函数并将控件添加到页面后调用它,但这与您所拥有的没有太大不同,尽管我可能出于样式原因选择它。

很高兴您找到问题的答案!

Well there is always adding your own load event and calling it after you have ran the constructor and added the control to the page, but it's not a lot different than what you have, although I might choose it for style reasons.

Glad you found an answer to your issue!

少年亿悲伤 2024-07-14 14:40:26

我对日历控件 DayRender 事件也有类似的问题,因为我想将用户控件添加到 e.Cell.Controls 集合中。 在尝试了几种失败的方法(用户控件 page_load 未触发或 ascx 上的列表框抛出空异常)后,我发现如果我使用 LoadControl(ascx) 初始化表单上的控件,然后开始访问ascx,一切正常。 这种方法根本不依赖于 ascx 上的 Page_Load 事件。

ASCX 标记

背后的代码

公共类 CPCalendarCell
继承 System.Web.UI.UserControl

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

End Sub

Public Sub Add(txt As String)
    Dim li As New ListItem(txt, txt)
    lstDay.Items.Add(li)
End Sub

End Class

页面 ASPX 标记

表单上 Calendar DayRender 事件背后的代码

Private Sub Calendar1_DayRender(sender As Object, e As System.Web.UI.WebControls.DayRenderEventArgs) Handles Calendar1.DayRender
    Dim div As CPCalendarCell = LoadControl("~/UserControls/CPCalendarCell.ascx")
    div.ID = "dv_" & e.Day.Date.ToShortDateString.Replace(" ", "_")

    **e.Cell.Controls.Add(div)**

    div.Add(e.Day.Date.Month.ToString & "/" & e.Day.Date.Day.ToString)
    div.Add("Item 1")
    div.Add("Item 2")
    e.Cell.Style.Add("background-color", IIf(e.Day.IsWeekend, "whitesmoke", "white").ToString)
End Sub

I had a similar issue with the Calendar control DayRender event, in that I wanted to add a user control to the e.Cell.Controls collection. After trying a couple of failed approaches with the user control page_load not firing or the listbox on the ascx throwing a null exception, I found that if I initialized my control on the form with LoadControl(ascx) and then start accessing the markup controls on the ascx, everything worked fine. This approach does not depend upon the Page_Load event on the ascx at all.

ASCX markup

code behind

Public Class CPCalendarCell
Inherits System.Web.UI.UserControl

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

End Sub

Public Sub Add(txt As String)
    Dim li As New ListItem(txt, txt)
    lstDay.Items.Add(li)
End Sub

End Class

page ASPX markup

code behind Calendar DayRender event on the form

Private Sub Calendar1_DayRender(sender As Object, e As System.Web.UI.WebControls.DayRenderEventArgs) Handles Calendar1.DayRender
    Dim div As CPCalendarCell = LoadControl("~/UserControls/CPCalendarCell.ascx")
    div.ID = "dv_" & e.Day.Date.ToShortDateString.Replace(" ", "_")

    **e.Cell.Controls.Add(div)**

    div.Add(e.Day.Date.Month.ToString & "/" & e.Day.Date.Day.ToString)
    div.Add("Item 1")
    div.Add("Item 2")
    e.Cell.Style.Add("background-color", IIf(e.Day.IsWeekend, "whitesmoke", "white").ToString)
End Sub
深白境迁sunset 2024-07-14 14:40:26

这里是 Steven Robbins 撰写的博客文章。 这篇文章解释了如何使用 LoadControl 传递用户控件的参数,类似于 LoadControl(Type, object[]) 的做法,除了它可以工作:)

Here is a blog post written by Steven Robbins. The post explains how to pass parameters for a user control using LoadControl, similar to what LoadControl(Type, object[]) would do, except it works :)

囍孤女 2024-07-14 14:40:26

根据 asp.net 页面生命周期,您的控件未完全添加到预渲染中,为什么不直接加载 page_load 中的值?

Per the asp.net page lifecycle your controls are not fully added in pre-render, why don't you just load the values in page_load?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文