2011-10-05 42 views
5

Tôi có một lớp (MyClass) đại diện cho một hệ thống phân cấp lồng nhau, vì vậy lớp này có thuộc tính là tập hợp MyClass. MyClass cũng có một thuộc tính tiêu đềTự động thêm điều khiển người dùng vào bộ lặp

Để hiển thị nó trên một trang web, tôi đã hy vọng tạo ra một điều khiển người dùng có bộ lặp. Trong mục mẫu, tôi sẽ có chữ để hiển thị thuộc tính tiêu đề và trên sự kiện ItemCreated của bộ lặp, tôi sẽ tạo một thể hiện mới của usercontrol và thêm nó vào mục hiện tại trong bộ lặp.

Vấn đề của tôi là khi sự kiện Page_Load trong bảng điều khiển người dùng kích hoạt, nếu điều khiển được thêm động, repORTty repMyClass repeater là null, ngay cả khi tôi gọi EnsureChildControls. Am i thiếu cái gì ở đây? Nếu tôi tạo ra một repeater và thả userctonrol của tôi trong mục mẫu nó hoạt động tốt. Tôi không thể làm điều này để làm việc năng động?

Bản quyền thuộc về:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="MyControl.ascx.cs" Inherits="MyControl" %> 
Items:<br/> 
<asp:Repeater ID="repMyClass" runat="server" EnableViewState="false" 
    OnItemCreated="repMenuItems_ItemCreated"> 
    <HeaderTemplate><ul><HeaderTemplate> 
    <ItemTemplate> 
     <li><%# Eval("Title") %> 
      <div><asp:PlaceHolder ID="SubItemPlaceholder" runat="server" /></div> 
     </li></ItemTemplate> 
    <FooterTemplate></ul></FooterTemplate> 
</asp:Repeater> 

User Control Code:

public partial class MyControl: System.Web.UI.UserControl 
{ 
    public IEnumerable<MyClass> ChildItems { get; set; } 
    protected void Page_Load(object sender, EventArgs e) 
    { 
     this.repMyClass.DataSource = ChildItems; 
     this.repMyClass.DataBind(); 
    } 

    protected void repMenuItems_ItemCreated(object Sender, RepeaterItemEventArgs e) 
    { 
     if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item) 
     { 
      //Get the MyClass instance for this repeater item 
      MyClass mcCurrent = (MyClass)e.Item.DataItem; 

      //If the MyClass instance has child instances 
      if (mcCurrent.Children != null && mcCurrent.Children.Length > 0) 
      { 
       //Add a new user control and set it's property so it can bind 
       PlaceHolder ph = (PlaceHolder)e.Item.FindControl("SubItemPlaceholder"); 

       MyControl ctl = (MyControl)Page.LoadControl(typeof(MyControl),new object[] {}); 

       ctl.ChildItems = mcCurrent.Children; 
       ph.Controls.Add(ctl); 
      } 
     } 
    } 
} 
+0

Bạn có thể chỉnh sửa điều này để giải thích và có thể làm sạch điều này. Tôi nghĩ có lẽ bạn đã có một nửa sửa đổi trong câu này mà không được hoàn thành? "Vấn đề của tôi là, khi sự kiện Page_Load đầu tiên cho các điều khiển được thêm động, repNyClass repeater poroperty là null" – chrismay

Trả lời

0

Bạn có thể thực hiện một constructor trong việc kiểm soát mà mất tài sản mà bạn muốn và sử dụng nó trong trường hợp tải, và sau đó vượt qua nó trong mảng đối tượng hiện đang trống trong LoadControl() gọi.

Cách tiếp cận khác là kích hoạt logic trong setter của thuộc tính thay vì trong sự kiện Load của điều khiển, vì về cơ bản là tải thực tại đây và kích hoạt một lần cho mỗi yêu cầu trên mỗi điều khiển nếu tôi làm đúng.

Một cách tiếp cận khác không phải là tải tự động như tất cả.

bên trong mẫu mục của bạn, bạn có thể có một cái gì đó như:

<uc:MyControl runat="server 
    ChildItems='<%# ((MyClass) Container.DataItem).Children %>' 
    Visible='<%# ((MyClass) Container.DataItem).Children.Length > 0 %>' 
    /> 

Cập nhật

Thêm một cách tiếp cận mà không bao giờ cho tôi lỗi với các điều khiển con trong điều khiển người dùng bên trong bộ lặp hoặc trang vòng đời, là để sử dụng sự kiện Item Data Bound thay vì Item Created.

Thực ra, khi tôi nghĩ về nó ngay bây giờ, mã của bạn không nên vì e.Item.DataItem vẫn chưa bị ràng buộc.

Cố gắng thay đổi sự kiện thành ItemDataBound và xem điều này có hiệu quả không.

.

Tôi vẫn khuyên bạn nên bao gồm điều khiển trong đánh dấu mục và kiểm soát khả năng hiển thị của điều khiển trong sự kiện (bây giờ là ItemDataBound). Bạn có thể tham khảo điều khiển bằng một cái gì đó như e.Item.FindControl("ControlId") as MyControl (sẽ trả về null nếu không tìm thấy trong mục hiện tại).

Hãy thử kết hợp cả hai, hoặc ít nhất là thay đổi sự kiện vào dữ liệu ràng buộc thay vì tạo ra, và chúng ta hãy xem ...

+0

Vấn đề là, điều khiển người dùng của tôi có các điều khiển con riêng (một bộ lặp trong trường hợp này). Trong sự kiện page_load của điều khiển người dùng, biến lặp lại thực sự là null. Tôi không thể đặt nó bản thân mình, khuôn khổ asp.net cần. – Jeremy

+0

Lý thuyết là bạn không cần phải sử dụng tải, thay vào đó hãy sử dụng setter. Một lựa chọn khác là trong bản cập nhật câu trả lời, có thể khắc phục sự cố. Tôi nghĩ rằng vấn đề là sự kiện được sử dụng, điều này có xác suất rất tốt là vấn đề. – Meligy

3

Tôi đã làm điều này một thời gian dài trước đây để tạo báo cáo lồng nhau sử dụng accordion.

Trong Index, khi bạn muốn tự động thêm trường hợp tài điều khiển:

// Declare Placeholder  
PlaceHolder ph = (PlaceHolder)e.Item.FindControl("SubItemPlaceholder") 

// Adding some literal controls to header 
ph.Controls.Add(new LiteralControl("This is the accordion header!!")); 

// Declare new control variable 
crt = new Control(); 

// Load up your User Control 
crt = LoadControl("~/MyControl.ascx"); 

// Check if it has loaded properly 
if (crt != null) 
{ 
    // GET/SET any custom properties of the User Control 
    ((myClass)crt).title = "Welcome"; 

    // Add the new User Control to the placeholder's controls collection 
    ph.Controls.Add(crt); 
} 

Lưu ý: Trong User Control, bạn phải thêm "ClassName" trong thẻ khai

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="MyControl.ascx.cs" Inherits="myTest" ClassName="myClass" %> 

Ngoài ra, bất kỳ thuộc tính nào bạn muốn hiển thị khi tạo các phiên bản động, bạn khai báo chúng như sau:

public string title { get; set; } 

Vì vậy, nếu bạn muốn ép buộc giá trị khi tạo cho "repMyClass", bạn có thể đặt giá trị đó làm thuộc tính và chỉ định bất kỳ giá trị nào bạn muốn theo chương trình.

+0

Vấn đề là, điều khiển người dùng của tôi có điều khiển con riêng của nó (một bộ lặp trong trường hợp này). Trong sự kiện page_load của điều khiển người dùng, biến lặp lại thực sự là null. Tôi không thể đặt nó bản thân mình, khuôn khổ asp.net cần. – Jeremy

+0

@Jeremy: Chắc chắn bạn có thể. Chỉ cần tạo một thuộc tính của kiểu lặp. Sau đó bạn có thể truy cập nó, khởi tạo nó, làm bất cứ điều gì bạn muốn với nó. Xin vui lòng làm rõ - theo tôi bạn nên có một tài sản công cộng trong UserControl, trong tải trang của UserControl bạn nên sử dụng tài sản công cộng để ràng buộc dữ liệu vào bộ lặp. Đúng không? –

Các vấn đề liên quan