2009-10-29 32 views
5

Tôi có một điều khiển người dùng mà tôi sử dụng trên nhiều trang để hiển thị thông tin về một đối tượng. Bất cứ khi nào tôi cần phải sử dụng điều này usercontrol, tôi gọi một phương pháp gọi là Hiển thị (trên usercontrol) và vượt qua trong một số giá trị.Thiết lập thuộc tính trên điều khiển người dùng bên trong vòng lặp foreach

public void Display(string name, List<Items> items) 
{ 
    // Set a few protected properties so I can display values from the aspx page 
} 

Điều này làm việc tốt, nhưng bây giờ tôi cần sử dụng điều khiển này trong vòng lặp foreach trong trang aspx.

<% foreach (var c in Categories) { %> 
     <uc:ItemsControl runat="server"/> 
<% } %> 

Đối tượng danh mục có phương pháp và thuộc tính mà tôi sẽ chuyển vào phương pháp Hiển thị. Vì vậy, làm thế nào tôi sẽ thiết lập các giá trị đúng cách?

tôi đã cố gắng làm cho tài sản trên các công điều khiển người dùng và chỉ cần thiết lập chúng theo cách này:

<uc:ItemsControl Items="<%# c.Items %>" 
       OtherProperty="<%# c.GetProperty() %>" 
       runat="server"/> 

này không làm việc, bởi vì các thuộc tính nhận được gửi đi trong là trống rỗng. Nếu tôi sử dụng <% = sau đó nó không hoạt động và thực sự ném một lỗi vì nó không nhận ra 'c' (trừ khi tôi cất cánh runat = "server" thì nó sẽ biên dịch ít nhất, nó vẫn không hoạt động .

cách thích hợp để làm điều này là gì

Edit:?. Ngoài ra, một điều khiển lặp có thể làm cho dễ dàng hơn này cho databinding, nhưng tôi muốn tránh việc sử dụng bất kỳ điều khiển .NET

Trả lời

0

Trong khi Justin Grant's answer có thể sẽ chỉ hoạt động tốt, chúng tôi quyết định chỉ cần tải điều khiển người dùng và gọi phương thức DisplayResults.

<% ((UserControlType)LoadControl("~/pathToUserControl.ascx")) 
     .DisplayResults(ItemName, ItemList)); %> 

Đó không phải là mã hoàn chỉnh, nhưng đó là những gì cần thiết để giải quyết vấn đề tôi đã giải quyết trong câu hỏi. Bằng cách tải điều khiển người dùng theo cách này, chúng tôi có thể đặt các thuộc tính chúng tôi cần và hiển thị điều khiển uesr với thông tin chính xác.

10

Trong trang WebForms, cách này thường được xử lý bằng cách sử dụng DataBinding, thay vì vòng lặp foreach, bạn có thể sử dụng điều khiển Repeater, đặt thuộc tính DataSource thành <%#Categories%> và sau đó sử dụng cú pháp ràng buộc dữ liệu trong latte của bạn Ví dụ ở trên, ngoại trừ thay vì c, bạn sẽ cần phải truyền Container.DataItem vào loại thích hợp trong kiểm soát của mình. Như thế này:

<%@ Page Language="C#" %> 
<script runat="server"> 
protected void Page_Load(object sender, EventArgs e) 
{ 
    CategoriesList.DataBind(); 
} 
class Category 
{ 
    public string CategoryName { get; set; } 
    public string GetProperty() { return CategoryName; } 
    public string[] Items { get { return new string[] {CategoryName + " 1", CategoryName + " 2"}; } } 
} 
Category[] Categories = new Category[] 
{ 
    new Category { CategoryName = "Shorts" }, 
    new Category { CategoryName = "Socks" }, 
    new Category { CategoryName = "Shirts" }, 
}; 
</script> 
<html> 
<body> 
<asp:Repeater runat="server" ID="CategoriesList" DataSource="<%# Categories %>"> 
    <ItemTemplate> 
    <uc:ItemsControl 
     Items="<%# ((Category)(Container.DataItem)).Items %>" 
     OtherProperty="<%# ((Category)(Container.DataItem)).GetProperty() %>" 
     runat="server"/> 
    </ItemTemplate>  
</asp:Repeater> 
</body> 
</html> 

Thông báo trước là bạn sẽ cần phải gọi phương thức DataBind() của Repeater somwhere, điển hình là trong phương pháp Page_Load.

Cá nhân, tôi luôn tìm thấy ràng buộc dữ liệu là một nỗi đau - cả việc truyền và nhu cầu gọi dữ liệu liên kết cảm thấy ít tự nhiên hơn tôi so với phương pháp foreach mà bạn đã thử ở trên. Đó có lẽ là điều tôi thích nhất về ASP.NET MVC - xem MVC của bạn có thể dễ dàng hơn nhiều bằng cách sử dụng mô hình foreach của iteration đó là nhiều hơn nữa đơn giản, IMHO. Điều đó nói rằng, nếu bạn phải gắn bó với WebForms, databinding-with-casting là con đường của kháng cự ít nhất.

BTW, cách tiếp cận của bạn ở trên đã không làm việc vì:

  1. thuộc tính runat = server ASP.NET kiểm soát không thể được lấp đầy bằng <%= %> syntax-- đó chỉ hữu ích cho đầu ra văn bản đơn giản, không để điền vào các thuộc tính đối tượng.

  2. sử dụng cú pháp liên kết dữ liệu (<%# %>) chắc chắn có thể được sử dụng để điền trong thuộc tính kiểm soát, nhưng bạn cần để bọc điều khiển trong một liên kết dữ liệu container (giống như một Repeater) và gọi DataBind() để có được sự thay thế xảy ra.

+1

Bộ lặp lại có thể là cách thích hợp, nhưng chúng tôi cố gắng tránh sử dụng các điều khiển .NET bất cứ khi nào có thể và thích đi với việc tạo HTML. – Brandon

+0

Vâng, tôi cũng vậy-- Tôi cũng tìm thấy cách tiếp cận vòng lặp-emit-HTML đơn giản hơn nhiều. Đó là lý do tại sao tôi thích ASP.NET MVC. Nhưng với các biểu mẫu Web, nếu bạn đã sử dụng các điều khiển tùy chỉnh của riêng bạn và cần đưa các thuộc tính của chúng, đặc biệt là trong một vòng lặp, sử dụng ràng buộc dữ liệu là cách dễ nhất để đi. Trong tò mò, tại sao tránh điều khiển tích hợp của asp.net? Đây có phải là mối quan tâm liên quan đến hiệu suất hay thứ gì khác không? Việc kiểm soát lặp lại là * rất * xương trần và nhanh chóng - và không gây ra hiện tượng quang tuyến hay các vết nứt khác như thế. Bộ lặp có thể hoạt động giống như một vòng lặp foreach giả mạo như một điều khiển. –

+0

Đó là một mối quan tâm nhất quán/hiệu suất. Sếp của tôi ban đầu tránh xa việc có các điều khiển .NET trong dự án vì các điều khiển/AjaxToolKit quá nặng nề cho những gì chúng ta cần, do đó, một cách tiếp cận HTML/jQuery thuần túy đã được thực hiện. Nếu thất bại, tôi có thể ném vào một bộ lặp đơn, tôi chỉ tự hỏi liệu có cách nào để làm điều này bằng cách sử dụng đường dẫn mà chúng ta đã bắt đầu. – Brandon

1

Tôi biết điều này là cũ, nhưng tôi tìm thấy chủ đề này thông qua google khá tức thì vì vậy tôi sẽ chỉ cần gõ này.

Tôi vừa mới nhận thấy khi giúp một đồng nghiệp rằng bạn có thể làm như thế này với UserControls trong foreach. Lưu ý rằng tôi đã chỉ thử nghiệm nó thông qua ví dụ của mình.

<% foreach (var c in Categories) { %> 
     <uc:ItemsControl runat="server" ID="ucItem"/> 
<% 
ucItem.PropertyToChange = c.Property; 
} %> 

Nếu điều này không áp dụng được cho bạn ít nhất có thể cho người khác.

+1

Bạn cần đặt thuộc tính trước khi gọi điều khiển. Nhưng nếu không, tiện dụng nếu đó là một trường hợp đơn giản của một cá thể đơn của một điều khiển được sử dụng trong một vòng lặp. – Reuben

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