代码之家  ›  专栏  ›  技术社区  ›  Brandon

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

  •  5
  • Brandon  · 技术社区  · 15 年前

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

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

    这很好,但是现在我需要在ASPX页的foreach循环中使用这个控件。

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

    Categories对象具有方法和属性,否则我将传递给显示方法。那么,如何正确设置这些值呢?

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

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

    这不起作用,因为接收到的属性是空的。如果我使用<%=则它不起作用,实际上会抛出一个错误,因为它不识别“c”(除非我去掉runat=“server”,否则它至少会编译,但它仍然不起作用。

    正确的方法是什么?

    编辑:另外,中继器控件可能使数据绑定更容易,但我更希望避免使用任何.NET控件。

    3 回复  |  直到 11 年前
        1
  •  10
  •   Justin Grant    15 年前

    在WebForms页面中,通常使用数据绑定来处理这种情况。您可以使用 Repeater 控件,将其DataSource属性设置为 <%#Categories%> ,然后在上面的后一个示例中使用数据绑定语法,除非 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>
    

    唯一需要注意的是,您需要调用repeater somwhere的databind()方法,通常在 Page_Load 方法。

    就我个人而言,我一直认为数据绑定是一种痛苦——对我来说,强制转换和调用数据绑定的需要都比您上面尝试的foreach方法要自然得多。这可能是我最喜欢的关于ASP.NET MVC的东西——您的MVC视图可以更容易地使用foreach迭代模型,它更简单,imho。也就是说,如果必须坚持使用WebForms,那么使用Casting进行数据绑定是阻力最小的途径。

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

    1. runat=server ASP.NET控件属性不能使用 <%= %> 语法——那只是有用的 用于纯文本输出,而不是用于 填充对象属性。

    2. 使用数据绑定语法( <%# %> )绝对可以用来填充 在控件属性中,但您需要 在数据绑定中包装控件 容器(像中继器)和呼叫 databind()以获取 将发生替换。

        2
  •  1
  •   peterthegreat    11 年前

    我知道这很古老,但我很快就通过谷歌找到了这个线索,所以我只需要输入这个。

    我刚刚注意到,在帮助同事时,您可以使用foreach中的用户控件这样做。注意,我只是通过他的例子来测试它。

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

    如果这不适用于你,至少对其他人来说是这样。

        3
  •  0
  •   Community Stefan Steinegger    7 年前

    同时 Justin Grant's answer 很可能HAV工作得很好,我们决定只加载用户控件并调用DisplayResults方法。

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

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