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

发布于 2024-08-08 21:59:15 字数 885 浏览 5 评论 0原文

我有一个用户控件,我在多个页面上使用它来显示有关对象的信息。每当我需要使用此用户控件时,我都会调用一个名为 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"/>
<% } %>

类别对象具有我本来会传递到 Display 方法中的方法和属性。那么我该如何正确设置这些值呢?

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

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

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

执行此操作的正确方法是什么?

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

I have a user control that I use on multiple pages to show information about an object. Whenever I need to use this usercontrol, I call a method called Display (on the usercontrol) and pass in some values.

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

This works fine, but now I need to use this control inside a foreach loop in an aspx page.

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

The categories object has the methods and properties that I would otherwise pass into the Display method. So how would I properly set the values?

I tried making the properties on the user control public and just setting them in this way:

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

This doesn't work, because the properties getting sent in are empty. If I use <%= then it doesn't work and actually throws an error because it doesn't recognize 'c' (unless I take off runat="server" then it will at least compile, it still won't work though.

What is the proper way to do this?

Edit: Also, a repeater control might make this easier for databinding, but I'd prefer to avoid the use of any .NET controls.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

挖个坑埋了你 2024-08-15 21:59:15

在 WebForms 页面中,通常使用 DataBinding 来处理此问题。您可以使用 Repeater 代替 foreach 循环 控件,将其 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 的 DataBind() 方法,通常是在 Page_Load 方法中。

就我个人而言,我一直发现数据绑定很痛苦——对我来说,转换和调用数据绑定的需要都比您上面尝试的 foreach 方法更不自然。这可能是我最喜欢 ASP.NET MVC 的一点——您的 MVC 视图可以更轻松地使用迭代的 foreach 模型,这更简单,恕我直言。也就是说,如果您必须坚持使用 WebForms,则数据绑定与转换是阻力最小的途径。

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

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

  2. 使用数据绑定语法(<%# %>)绝对可以用来填充
    在控制属性中,但你需要
    将控件包装在数据绑定中
    容器(如中继器)并调用
    DataBind() 为了得到
    发生替换。

In a WebForms page, the way this is usually handled by using DataBinding. Instead of a foreach loop, you can use a Repeater control, set its DataSource property to <%#Categories%>, and then use the data-binding syntax in your latter example above, except instead of c, you'll need to cast Container.DataItem to the proper type in your control. Like this:

<%@ 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>

The only caveat is you'll need to call the DataBind() method of the Repeater somwhere, typically in the Page_Load method.

Personally, I have always found data-binding to be a pain-- both the casting and the need to call data-bind feel much less natural to me than the foreach method you tried above. That's probably the thing I like best about ASP.NET MVC-- your MVC Views can much more easily use the foreach model of iteration which is much more straightforward, IMHO. That said, if you have to stick with WebForms, databinding-with-casting is the path of least resistance.

BTW, your approaches above didn't work because:

  1. runat=server ASP.NET control properties cannot be filled using
    <%= %> syntax-- that's only useful
    for plain-text output, not for
    filling in object properties.

  2. using data-binding syntax ( <%# %>) can definitely be used to fill
    in control properties, but you need
    to wrap the control in a data-binding
    container (like a Repeater) and call
    DataBind() in order to get the
    replacement to happen.

是你 2024-08-15 21:59:15

我知道这已经很旧了,但我通过谷歌很快发现了这个线程,所以我只需输入这个。

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

<% foreach (var c in Categories) { %>
<%    MyControl ctrl = (MyControl)FindControl("ucItem"); %>
<%    ctrl.PropertyToChange = c.Property; %>

      <uc:MyControl runat="server" ID="ucItem"/>
<% } %>

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

I know this is old, but I found this thread through google quite instant so I'll just type this.

I've just noticed when helping a colleague that you could do like this with UserControls in foreach. Note that I've only tested it through his example.

<% foreach (var c in Categories) { %>
<%    MyControl ctrl = (MyControl)FindControl("ucItem"); %>
<%    ctrl.PropertyToChange = c.Property; %>

      <uc:MyControl runat="server" ID="ucItem"/>
<% } %>

If this is not applicable for you at least it might be for others.

何以心动 2024-08-15 21:59:15

贾斯汀·格兰特的回答可能会工作得很好,我们决定只加载用户控件并调用 DisplayResults 方法。

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

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

While Justin Grant's answer would likely hav worked just fine, we decided to go with just loading the user control and calling the DisplayResults method.

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

That is not the complete code, but it is what was needed to solve the issue I addressed in the question. By loading the user control this way, we could set the properties we needed and display the uesr control with the correct information.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文