2008-10-27 37 views
15

Tôi gặp sự cố khi sử dụng LoadControl(type, Params). Hãy để tôi giải thích ...Asp.net Usercontrol LoadControl Issue

Tôi có một điều khiển người dùng siêu đơn giản (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" /> 

với mã (C#) đằng sau của:

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; 
     } 
    } 
} 

Ở những nơi khác trong ứng dụng web của tôi Tôi thêm một ví dụ về điều khiển người dùng tới trang bằng cách sử dụng mã sau:

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

Tôi đang sử dụng phiên bản quá tải LoadControl vì tôi muốn chuyển thông số Message tới hàm tạo. Tất cả điều này xuất hiện để hoạt động ok.

Tuy nhiên, khi OnPreRender() được kích hoạt trên người dùng ErrorDisplay, việc kiểm soát biến lblTitle và lblDescription là cả hai null, mặc dù chúng có tương đương đánh dấu. Biến tin nhắn đã được điền chính xác.

Có ai có thể tiết lộ bất kỳ ánh sáng nào về lý do điều này có thể xảy ra không?

Cảm ơn

EDIT:

Chỉ cần cho rõ ràng tôi cũng sẽ thêm rằng mã được programatically thêm usercontrol trang đang chạy để đáp ứng với một nút bấm, do đó 'lưu trữ trang 'đã tiến triển qua Init, Page_Load và hiện đang xử lý các trình xử lý sự kiện.

Tôi không thể thêm các liên kết người dùng ở giai đoạn vòng đời asp trước đó khi chúng được tạo ra để phản hồi sự kiện nhấp nút.

Trả lời

19

Tôi đã thử đoạn mã sau cũng - trong đó sản lượng kết quả tương tự (ví dụ cả lblTitle và lblDescription là null)

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

tôi đã có sự hiểu biết rằng chức năng LoadControl mang sự kiểm soát nó được tải lên đến 'trạng thái' hiện tại của trang mà nó đang được đưa vào. do đó Init, Page_Load vv được chạy như một phần của cuộc gọi LoadControl.

Thú vị điều này (chưa được trả lời) diễn đàn asp.net đăng triển lãm cùng một vấn đề như tôi đang gặp.

MSDN Forums Post

Ngoài - Từ MSDN:

Khi bạn tải một điều khiển vào một điều khiển container, container tăng tất cả các sự kiện điều khiển bổ sung cho đến khi nó đã bắt kịp với sự kiện hiện tại. Tuy nhiên, điều khiển bổ sung không bắt kịp với xử lý dữ liệu postback.Đối với một điều khiển bổ sung để tham gia xử lý dữ liệu postback, bao gồm xác thực, điều khiển phải được thêm vào sự kiện Init thay vì trong sự kiện Tải.

Do đó không nên LoadControl điều chỉnh chính xác sự kiểm soát của bộ phận kiểm soát?

EDIT:

Ok, vì vậy tôi trả lời câu hỏi của riêng tôi ở đây ..

Tôi tìm thấy một phiên bản trả lời của các bài diễn đàn tôi liên kết với trên Here

Về cơ bản các câu trả lời là LoadControl(type, params) không thể suy ra 'trang đầu tiên' ascx để phân tích cú pháp và do đó nó không gây phiền toái cho bất kỳ điều khiển nào. Khi bạn sử dụng phiên bản LoadControl("ascx path"), nó được đưa ra trang trước và do đó tất cả phân tích cú pháp và initalision.

Vì vậy, trong tóm tắt, tôi cần phải thay đổi mã đó là initalising kiểm soát và chia nó thành các phần riêng biệt. I E.

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

Và nó sẽ hoạt động ok .. Nó không phải là gọn gàng như nỗ lực trước đây của tôi, nhưng ít nhất nó sẽ hoạt động.

Tôi vẫn đang mở để đề xuất cải thiện điều trên.

Cheers

+3

+1 và lời cảm ơn từ tôi về việc giải quyết vấn đề tôi đang gặp phải. :) –

+0

Theo dõi tuyệt vời! –

-1

Mỗi vòng đời trang asp.net các điều khiển của bạn không được thêm đầy đủ vào trước khi kết xuất, tại sao bạn không tải các giá trị trong page_load?

+1

Đây không phải là chính xác. [PreRender xảy ra sau khi tải.] (Http://msdn.microsoft.com/en-us/library/ms178472.aspx#lifecycle_events) 'Lớn lên sau khi đối tượng Trang đã tạo tất cả các điều khiển ' – Chris

0

Đồng ý với Mitchel, bạn sẽ có thể đặt một page_load trong chính mã kiểm soát mà sẽ kích hoạt sau khi các điều khiển hoàn toàn có sẵn.

+1

[PreRender xảy ra * sau * Tải] (http://msdn.microsoft.com/en-us/library/ms178472.aspx#lifecycle_events), vì vậy PreRender phải an toàn. – Chris

0

Vâng có phải lúc nào cũng thêm sự kiện load của riêng bạn và gọi đó là sau khi bạn đã chạy các nhà xây dựng và bổ sung điều khiển để trang, nhưng nó không phải là rất nhiều khác biệt so với những gì bạn có, mặc dù tôi có thể chọn nó vì lý do phong cách.

Rất vui khi bạn tìm thấy câu trả lời cho vấn đề của mình!

0

Here là một bài đăng blog được viết bởi Steven Robbins. Các bài giải thích làm thế nào để vượt qua các thông số cho một điều khiển người dùng sử dụng LoadControl, tương tự như những gì LoadControl(Type, object[]) sẽ làm gì, trừ nó hoạt động :)

0

Tôi đã có một vấn đề tương tự với sự kiện DayRender Lịch kiểm soát, trong đó tôi muốn thêm người dùng kiểm soát bộ sưu tập e.Cell.Controls. Sau khi thử một vài cách tiếp cận thất bại với page_load control không được kích hoạt hoặc listbox trên ascx ném một ngoại lệ null, tôi thấy rằng nếu tôi khởi tạo điều khiển của mình trên form với LoadControl (ascx) và sau đó bắt đầu truy cập các điều khiển đánh dấu trên ascx, mọi thứ đều ổn. Cách tiếp cận này không phụ thuộc vào sự kiện Page_Load trên ascx.

đánh dấu ascx

mã sau

Công Lớp 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

trang ASPX đánh dấu

mã sau sự kiện Lịch DayRender về hình thức

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 
Các vấn đề liên quan