【发布时间】:2018-06-10 02:12:07
【问题描述】:
我正在使用嵌套的用户控件来实现某些东西,并且遇到了与数据绑定相关的问题,因此我创建了一个小应用程序来尝试调试该行为。
我有一个包含单个用户控件“ChildControl”的默认页面 (aspx)。在后面的代码中,我为 ChildControl 设置了几个属性并在其上调用 DataBind()。
在 ChildControl 用户控件 (ascx) 中,我有一个“GrandchildControl”ListViewItems 的 ListView,它有一个绑定到在 Default.aspx 的 LoadPage() 方法中设置的属性的数据源。我还绑定了 GrandchildControl 的一个属性,该属性将用于该用户控件中的 DropDownList。在此用户控件的代码中,我有一个单击事件处理程序,它只是将一个新的用户对象添加到会话变量并调用 Default.aspx 的 LoadPage() 方法。
在 GrandchildControl 用户控件 (ascx) 中,我正在显示每个绑定的用户对象的信息。
我已添加日志以查看调用事件的顺序。当我导航到页面(不是回发)时,事件按预期按以下顺序触发:
DEFAULT PAGE LOAD
GRANDCHILD CONTROL ITEM DATA BOUND
GRANDCHILD CONTROL ITEM DATA BOUND
CHILD CONTROL PAGE LOAD
GRANDCHILD CONTROL PAGE LOAD
GRANDCHILD CONTROL PAGE LOAD
但是,当我单击 ChildControl 中的 LinkButton 以添加新的用户对象时,事件按以下顺序触发:
DEFAULT PAGE LOAD
CHILD CONTROL PAGE LOAD
GRANDCHILD CONTROL PAGE LOAD
GRANDCHILD CONTROL PAGE LOAD
ADD INCOME CLICKED
GRANDCHILD CONTROL PAGE LOAD
GRANDCHILD CONTROL ITEM DATA BOUND
GRANDCHILD CONTROL PAGE LOAD
GRANDCHILD CONTROL ITEM DATA BOUND
GRANDCHILD CONTROL PAGE LOAD
GRANDCHILD CONTROL ITEM DATA BOUND
如您所见,在调用各自的页面加载触发后,用户对象被绑定到 ListView。因此,下拉选项设置不正确(它们都默认为 0 索引)。
所以我的问题是,是什么导致 ucChildControl.DataBind() 在页面最初加载时的行为与从 ChildControl 的点击处理程序的上下文中调用时的行为不同?
我为这篇冗长的帖子道歉,但我想尽可能多地显示细节,因为我已经搜索过并且无法找到类似的问题和解决方案。
所有代码如下:
型号:
public class DropdownContainer
{
public List<DropdownValue> DropdownValues { get; set; }
}
public class DropdownValue
{
public string DisplayText { get; set; }
public string ID { get; set; }
}
public class User
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string AgeGroup { get; set; }
}
aspx前端:
<asp:Content runat="server" ID="BodyContent" ContentPlaceHolderID="MainContent">
<uc1:ChildControl runat="server" ID="ucChildControl"></uc1:ChildControl>
</asp:Content>
aspx代码后面:
public partial class Default : Page
{
private DropdownContainer _ageGroupContainer = new DropdownContainer()
{
DropdownValues = new List<DropdownValue>()
{
new DropdownValue()
{
DisplayText = "18-25",
ID = "1"
},
new DropdownValue()
{
DisplayText = "26-35",
ID = "2"
},
new DropdownValue()
{
DisplayText = "36-45",
ID = "3"
}
}
};
private List<User> _userDataSource = new List<User>()
{
new User()
{
FirstName = "Mickey",
LastName = "Mouse",
AgeGroup = "1"
},
new User()
{
FirstName = "Daffy",
LastName = "Duck",
AgeGroup = "3"
}
};
public string Log { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
Log += "DEFAULT PAGE LOAD\n";
if (!Page.IsPostBack)
{
LoadPage();
}
}
public void LoadPage()
{
List<User> lstUserTemp = _userDataSource;
if (Session["usersAdded"] != null)
{
lstUserTemp.AddRange((List<User>)Session["usersAdded"]);
}
ucChildControl.UserDataSource = lstUserTemp;
ucChildControl.AgeGroupDataSource = _ageGroupContainer;
ucChildControl.DataBind();
}
}
子 ascx 前端:
<div>
<asp:ListView runat="server" ID="lvChild" DataSource='<%# UserDataSource %>' OnItemDataBound="lvChild_ItemDataBound">
<ItemTemplate>
<uc2:GrandchildControl runat="server" ID="ucGrandchildControl" User='<%# Container.DataItem %>' AgeGroupDataSource='<%# AgeGroupDataSource %>'></uc2:GrandchildControl>
<br />
</ItemTemplate>
</asp:ListView>
</div>
<asp:LinkButton runat="server" ID="lbtnAddUser" OnClick="lbtnAddUser_Click" Text="Add User"></asp:LinkButton>
后面的子ascx代码:
public partial class ChildControl : System.Web.UI.UserControl
{
public List<User> UserDataSource { get; set; }
public DropdownContainer AgeGroupDataSource { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
((Default)Page).Log += "CHILD CONTROL PAGE LOAD\n";
}
protected void lvChild_ItemDataBound(object sender, ListViewItemEventArgs e)
{
((Default)Page).Log += "GRANDCHILD CONTROL ITEM DATA BOUND\n";
}
protected void lbtnAddUser_Click(object sender, EventArgs e)
{
((Default)Page).Log += "ADD USER CLICKED\n";
List<User> usersAdded = (List<User>)Session["usersAdded"];
if (usersAdded == null)
{
usersAdded = new List<User>();
}
usersAdded.Add(new User());
Session["usersAdded"] = usersAdded;
((Default)Page).LoadPage();
}
}
孙子 ascx 前端:
<div>
<asp:Label runat="server" Text="User Name: "></asp:Label>
<asp:TextBox runat="server" ID="txtUserName" Text='<%# string.Format(@"{0} {1}", User.FirstName, User.LastName) %>'></asp:TextBox>
</div>
<div>
<asp:Label runat="server" Text="Age Group: "></asp:Label>
<asp:DropDownList runat="server" ID="ddlAgeGroup" DataSource='<%# AgeGroupDataSource.DropdownValues.OrderBy(x => Convert.ToInt32(x.ID)) %>' DataTextField="DisplayText" DataValueField="ID" OnSelectedIndexChanged="ddlAgeGroup_SelectedIndexChanged" AutoPostBack="true"></asp:DropDownList>
</div>
孙子ascx代码后面:
public partial class GrandchildControl : System.Web.UI.UserControl
{
public User User { get; set; }
public DropdownContainer AgeGroupDataSource { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
((Default)Page).Log += "GRANDCHILD CONTROL PAGE LOAD\n";
if (User != null)
{
ddlAgeGroup.SelectedValue = User.AgeGroup;
}
ddlAgeGroup.Items.Insert(0, new ListItem() { Text = "SELECT AN AGE GROUP", Value = string.Empty });
}
protected void ddlAgeGroup_SelectedIndexChanged(object sender, EventArgs e)
{
((Default)Page).Log += "GRANDCHILD CONTROL SELECTED INDEX CHANGED\n";
}
}
【问题讨论】:
标签: c# asp.net events data-binding webforms