【问题标题】:Setting properties on a user control inside a foreach loop在 foreach 循环内设置用户控件的属性
【发布时间】:2009-10-29 17:22:40
【问题描述】:

我有一个用户控件,我在多个页面上使用它来显示有关对象的信息。每当我需要使用这个用户控件时,我都会调用一个名为 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 对象具有我会传递给 Display 方法的方法和属性。那么我该如何正确设置这些值呢?

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

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

这不起作用,因为发送进来的属性是空的。如果我使用

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

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

【问题讨论】:

    标签: c# user-controls webforms


    【解决方案1】:

    在 WebForms 页面中,通常使用 DataBinding 来处理这种情况。您可以使用Repeater 控件代替foreach 循环,将其DataSource 属性设置为&lt;%#Categories%&gt;,然后使用上面后一个示例中的数据绑定语法,除了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 的 DataBind() 方法,通常在 Page_Load 方法中。

    就我个人而言,我一直觉得数据绑定是一件痛苦的事——无论是强制转换还是调用 data-bind 对我来说都比您上面尝试的 foreach 方法更不自然。这可能是我最喜欢 ASP.NET MVC 的地方——您的 MVC 视图可以更轻松地使用更直接的 foreach 迭代模型,恕我直言。也就是说,如果您必须坚持使用 WebForms,那么数据绑定与强制转换是阻力最小的路径。

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

    1. runat=server ASP.NET 控件属性无法使用 &lt;%= %&gt; 语法——这只是有用的 用于纯文本输出,不适用于 填写对象属性。

    2. 使用数据绑定语法(&lt;%# %&gt;)绝对可以用来填充 在控件属性中,但您需要 将控件包装在数据绑定中 容器(如中继器)并调用 DataBind() 以获取 替换发生。

    【讨论】:

    • 中继器可能是正确的方法,但我们尽量避免使用 .NET 控件,而是更喜欢生成 HTML。
    • 是的,我也是——我还发现循环和发射 HTML 方法更简单。这就是我喜欢 ASP.NET MVC 的原因。但是对于 Web 窗体,如果您已经在使用自己的自定义控件并且需要填充它们的属性,尤其是在循环中,那么使用数据绑定是最简单的方法。出于好奇,为什么要避免使用 asp.net 的内置控件?这是与性能相关的问题还是其他问题?转发器控件是非常 准系统和快速的 - 并且不会导致视图状态或其他类似的杂物。中继器可以像伪装成控件的 foreach 循环一样工作。
    • 更多的是一致性/性能问题。我的老板最初不再在项目中使用 .NET 控件,因为控件/AjaxToolKit 对于我们需要的东西来说太重了,因此采用了纯 HTML/jQuery 方法。如果一切都失败了,我可以投入一个中继器,我只是想知道是否有任何方法可以使用我们已经开始的路径来做到这一点。
    • 有一种方法可以做到这一点,但它需要更多的代码,难以维护,而且可能也会更慢。 :-) 回避复杂的内置控件(例如 DataGrid)当然有充分的理由,但 Repeater 真的非常非常小。顺便说一句,我绝对推荐查看 ASP.NET MVC——如果您喜欢纯 HTML 和 jquery,那么您将在 MVC 的天堂。 :-)
    • @Justin,我以前曾使用过它,你是对的,我确实更喜欢 MVC 而不是 Web 表单。我发现它更干净,更容易使用。希望我可以在不久的将来在新项目中使用它。另外,对您的答案+1。虽然这可能可行,但我们只使用 UC 的 Render 方法来提供标记。
    【解决方案2】:

    我知道这是旧的,但我很快就通过谷歌找到了这个帖子,所以我就输入这个。

    我刚刚在帮助一位同事时注意到,您可以使用 foreach 中的 UserControls 来执行此操作。请注意,我只是通过他的示例对其进行了测试。

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

    如果这不适用于你,至少它可能适用于其他人。

    【讨论】:

    • 调用控件前需要设置属性。但除此之外,如果它是循环中使用的单个控件实例的简单案例,则很方便。
    【解决方案3】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-07-27
      • 2011-07-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-17
      相关资源
      最近更新 更多