在foreach循环内设置用户控件的属性

Bra*_*don 5 c# user-controls webforms

我有一个用户控件,我在多个页面上使用它来显示有关对象的信息.每当我需要使用这个usercontrol时,我调用一个名为Display的方法(在usercontrol上)并传入一些值.

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

这工作正常,但现在我需要在aspx页面的foreach循环中使用此控件.

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

categories对象具有我将传递给Display方法的方法和属性.那么我该如何正确设置值呢?

我尝试在用户控件上公开属性,并以这种方式设置它们:

<uc:ItemsControl Items="<%# c.Items %>" 
                 OtherProperty="<%# c.GetProperty() %>" 
                 runat="server"/>
Run Code Online (Sandbox Code Playgroud)

这不起作用,因为发送的属性是空的.如果我使用<%=然后它不起作用,实际上抛出一个错误,因为它不识别'c'(除非我脱掉runat ="server"然后它至少会编译,它仍然无法工作但.

这样做的正确方法是什么?

编辑:此外,转发器控件可能使数据绑定更容易,但我宁愿避免使用任何.NET控件.

Jus*_*ant 10

在WebForms页面中,通常使用DataBinding处理此方法.您可以使用Repeater控件,将其DataSource属性设置为<%#Categories%>,然后在上面的示例中使用数据绑定语法,而不是foreach循环,除了代替之外c,您需要Container.DataItem在控件中强制转换为正确的类型.像这样:

<%@ 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>
Run Code Online (Sandbox Code Playgroud)

唯一需要注意的是,您需要调用Repeater somwhere的DataBind()方法,通常在Page_Load方法中.

就个人而言,我总是发现数据绑定是一种痛苦 - 对于我而言,转换和调用数据绑定的需要比我上面尝试的foreach方法更不自然.这可能是我最喜欢ASP.NET MVC的东西 - 你的MVC视图可以更容易地使用更简单的foreach迭代模型,恕我直言.也就是说,如果你必须坚持使用WebForms,那么数据绑定与铸造是阻力最小的路径.

顺便说一下,你的上述方法不起作用,因为:

  1. runat = server无法使用<%= %>语法填充ASP.NET控件属性 - 这仅对纯文本输出有用,而不是用于填充对象属性.

  2. 使用数据绑定语法(<%# %>)绝对可以用来填充控件属性,但是你需要将控件包装在数据绑定容器(如Repeater)中并调用DataBind()以便进行替换.


Bra*_*don 0

虽然Justin Grant 的答案可能效果很好,但我们决定只加载用户控件并调用 DisplayResults 方法。

<% ((UserControlType)LoadControl("~/pathToUserControl.ascx"))
       .DisplayResults(ItemName, ItemList)); %>
Run Code Online (Sandbox Code Playgroud)

这不是完整的代码,但它是解决我在问题中解决的问题所需的代码。通过这种方式加载用户控件,我们可以设置所需的属性并显示带有正确信息的 uesr 控件。