Repeater内的用户控件

15

我在Repeater控件中嵌套了一个UserControl。这个Repeater的数据源来自SQL Server。

User Control的.cs文件是MoviePanel.ascx.cs:


public int myMovieID { get; set; }
public string myMovieName { get; set; }
public string myMovieDescription { get; set; }

protected void Page_Load(object sender, EventArgs e)
{
   MovieIDLbl.Text = myMovieID.ToString();
   MovieNameLbl.Text = myMovieName;
   DescriptionLbl.Text = myMovieDescription;
}

ASPX页面:


<asp:Repeater ID="Repeater1" DataSourceID="ListOfMoviesDS" runat="server">
    <ItemTemplate>
        <uc1:MovieDetailPanel runat="server" myMovieID='<%# Eval("MovieID") %>' 
           myMovieName='<%# Eval("movieName") %>' 
                myMovieDescription='<%# Eval("movieDescription") %>' 
                id="MovieDetailPanel1" />

        <asp:Label ID="Label1" runat="server" 
              Text='<%# Eval("MovieID") %>'></asp:Label>
        <asp:Label ID="Label2" runat="server" 
              Text='<%# Eval("movieName") %>'></asp:Label>
        <asp:Label ID="Label3" runat="server" 
             Text='<%# Eval("movieDescription") %>'></asp:Label>
    </ItemTemplate>
</asp:Repeater>

这里发生了非常奇怪的事情。值没有传递到用户控件。然而,如果我在用户控件下面放置标签并使用 Eval() 设置文本,它就可以工作。你可能认为用户控件可能是问题所在。但是,如果我手动键入一些内容,例如用 <%# Eval("movieName") %> 替换它,它会被传递到用户控件并显示。

我毫无头绪!如果问题出在 Eval() 上,则标签也不应该获得文本。或者如果问题出在用户控件上,则我的手动文本就不应该被传递。我不知道为什么 Eval() 的值无法传递到用户控件。


请问我应该如何从代码后台向用户控件传递值?我可以为重复器分配数据源,但是数据源中的值如何传递到用户控件中呢? - user1220169
与论坛网站不同,我们不在 [so] 上使用“感谢”或“感激任何帮助”的用语,也不使用签名。请参阅“是否应从帖子中删除‘嗨’、‘谢谢’、标签行和问候语?”。 - John Saunders
你在页面生命周期的哪个时刻检查值是否已设置?你正在使用数据绑定表达式,因此这些将在“DataBinding”阶段设置。 - John Saunders
我正在检查UserControl的PageLoad事件(如上例所示)。这样做有问题吗? - user1220169
我理解你的问题。你能告诉我如何暂停控件直到值被设置/绑定吗?我的意思是,是否有一个事件函数可以添加以获取值,而不是从Page_Load()中执行它? - user1220169
2个回答

13

你的代码工作得很好;我测试过了(请查看页面底部)。最糟糕的情况是你可以尝试在ItemDataBound事件中分配这些值。

<asp:Repeater ID="Repeater1" runat="server" OnItemDataBound="Repeater1_ItemDataBound">
    <ItemTemplate>
        <uc1:MoviePanel runat="server" id="MovieDetailPanel1" />
    </ItemTemplate>
</asp:Repeater>

public class Movie
{
    public int MovieID { get; set; }
    public string MovieName { get; set; }
    public string MovieDescription { get; set; }
}

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        Repeater1.DataSource = new List<Movie>
        {
            new Movie {MovieID = 1, MovieName = "One", MovieDescription = "One hundred"},
            new Movie {MovieID = 2, MovieName = "Two", MovieDescription = "Two hundreds"},
            new Movie {MovieID= 3, MovieName = "Three", MovieDescription = "Three hundreds"},
        };
        Repeater1.DataBind();
    }
}

protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    if (e.Item.ItemType == ListItemType.Item ||
        e.Item.ItemType == ListItemType.AlternatingItem)
    {
        var movie = e.Item.DataItem as Movie;

        var control = e.Item.FindControl("MovieDetailPanel1") as MoviePanel;
        control.myMovieID = movie.MovieID;
        control.myMovieDescription = movie.MovieDescription;
        control.myMovieName = movie.MovieName;
    }
}

输入图像描述

以下是我如何测试您的原始问题

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebDemo.WebForm1" %>

<%@ Register src="MoviePanel.ascx" tagname="MoviePanel" tagprefix="uc1" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:Repeater ID="Repeater1" runat="server">
            <ItemTemplate>
                <uc1:MoviePanel runat="server" mymovieid='<% #Eval("MovieID") %>'
                    mymoviename='<% #Eval("movieName") %>'
                    mymoviedescription='<% #Eval("movieDescription") %>'
                    id="MovieDetailPanel1" />
            </ItemTemplate>
        </asp:Repeater>
    </form>
</body>
</html>


namespace WebDemo
{
    public partial class WebForm1 : System.Web.UI.Page
    {
        public class Movie
        {
            public int MovieID { get; set; }
            public string MovieName { get; set; }
            public string MovieDescription { get; set; }
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                Repeater1.DataSource = new List<Movie>
                {
                    new Movie {MovieID = 1, MovieName = "One", MovieDescription = "One hundred"},
                    new Movie {MovieID = 2, MovieName = "Two", MovieDescription = "Two hundreds"},
                    new Movie {MovieID= 3, MovieName = "Three", MovieDescription = "Three hundreds"},
                };
                Repeater1.DataBind();
            }
        }
    }
}

<%@ Control Language="C#" AutoEventWireup="true"
    CodeBehind="MoviePanel.ascx.cs" Inherits="WebDemo.MoviePanel" %>

<p>
    <strong>Inside Control</strong>:
    <asp:Label ID="MovieIDLbl" runat="server" />
    <asp:Label ID="MovieNameLbl" runat="server" />
    <asp:Label ID="DescriptionLbl" runat="server" />
</p>

namespace WebDemo
{
    public partial class MoviePanel : System.Web.UI.UserControl
    {
        public int myMovieID { get; set; }
        public string myMovieName { get; set; }
        public string myMovieDescription { get; set; }

        protected void Page_Load(object sender, EventArgs e)
        {
            MovieIDLbl.Text = myMovieID.ToString();
            MovieNameLbl.Text = myMovieName;
            DescriptionLbl.Text = myMovieDescription;
        }
    }
}

1
是的,但是你如何在用户控件上使用绑定?在这里,您正在重复器上使用绑定,但是然后没有在用户控件上使用绑定。相反,此代码手动设置了Text属性。这根本没有意义。如果它们不能使用绑定,那么使用用户控件的意义是什么? - Rhyous
@Rhyous 这可能是因为 OP 希望将某些业务逻辑与其他控件分离。 - Win

4

这里有一种方式,可以在代码后端完成所有操作。我不能说这是最佳实践,但这很简洁。你可以使用ItemDataBind事件,将项强制转换为你想要的类型,例如datatable,然后创建一个用户控件的新实例并将其添加到重复器的控件集合中。

页面源代码

public partial class _Default : Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        var myList = new List<string>() { "one", "two", "three" };
        myRepeater.DataSource = myList;
        myRepeater.DataBind();
    }

    public void R1_ItemDataBound(Object Sender, RepeaterItemEventArgs e)
    {
        var items = (string)e.Item.DataItem;
        var newcontrol = (WebUserControl1)Page.LoadControl("~/WebUserControl1.ascx");
        newcontrol.myTest = items;
        myRepeater.Controls.Add(newcontrol);           
    }   
}

页面 HTML

 <asp:Repeater ID="myRepeater"  runat="server" OnItemDataBound="R1_ItemDataBound">
    <ItemTemplate>

    </ItemTemplate>
</asp:Repeater>

用户控件

<h1 id="myLabel" runat="server"></h1>

并且

public partial class WebUserControl1 : System.Web.UI.UserControl
{
    public string myTest { get; set; }
    protected void Page_Load(object sender, EventArgs e)
    {
        myLabel.InnerText = myTest;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接