我看到很多关于这个主题的事情,但我无法找到解决方案。 我添加了许多下拉列表与一个事件,但他们没有触发SelectedIndexChanged evet。 这是drplist创建者代码:
foreach (var row in cmdSelectCats.ExecuteReader())
{
var id = row["ProductCategoryID"].ToString();
var dropDownStatus = new DropDownList {ID = "DrpStatus-" + id};
dropDownStatus.Items.Add(new ListItem("Aktif", "1"));
dropDownStatus.Items.Add(new ListItem("Pasif", "2"));
dropDownStatus.AutoPostBack = true;
dropDownStatus.SelectedIndexChanged += Status_SelectedIndexChanged;
var tableCell = new TableCell();
tableCell.Controls.Add(dropDownStatus);
dropDownStatus.SelectedValue = row["ProductCategoryStatusID"].ToString();
tableRow.Cells.Add(tableCell);
TblCatList.Rows.Add(tableRow);
}
当然是我的活动:
public void Status_SelectedIndexChanged(object sender, EventArgs e)
{
//DO SOMETHING
}
我缺少什么?
答案 0 :(得分:17)
这是一个常见问题,它与页面生命周期有关:
看看以下问题:
Click events on Array of buttons
Button array disappears after click event
Dynamically create an ImageButton
现在,在创建动态控件时要记住的基本步骤是:
PreInit
事件中创建动态控件,然后在Init
事件中创建控件if(!this.IsPostBack) this.CreatemyDynamicControls();
PreInit
或Init
事件中创建控件时,其状态将自动设置为发布事件,这意味着在LoadComplete
事件中您的控件将包含其状态即使您在每个帖子中再次创建它们,甚至在您没有明确设置其状态时也会返回。 注意当您处理在设计时创建的控件时,此行为是不同的,在这种情况下,已设置状态的事件是Load事件 PageLoadComplete
之前进行,否则将不会被提升请考虑MSDN中的以下描述
如果控件是在运行时动态创建的,或者在数据绑定控件的模板中以声明方式创建,则它们的事件最初不会与页面上其他控件的事件同步。例如,对于在运行时添加的控件,Init和Load事件可能在页面生命周期的后期发生,而不是以声明方式创建的控件的相同事件。因此,从它们实例化时起,模板中动态添加的控件和控件会一个接一个地引发它们的事件,直到它们赶上将它添加到Controls集合中的事件。
以上对我来说并不是那么清楚,但我发现了以下内容。在设计时创建以下TextBox
protected void Page_PreInit(object sender, EventArgs e)
{
this.txtDesignTextBox1.Text = "From PreInit";
this.txtDesignTextBox1.Text += DateTime.Now.ToString();
}
protected void Page_Init(object sender, EventArgs e)
{
this.txtDesignTextBox2.Text = "From Init";
this.txtDesignTextBox2.Text += DateTime.Now.ToString();
}
protected void Page_Load(object sender, EventArgs e)
{
this.txtDesignTextBox3.Text = "From Load";
this.txtDesignTextBox3.Text += DateTime.Now.ToString();
}
乍一看,您可能会认为在每个帖子中所有文本框都使用当前日期更新,但事实并非如此,因为它们是在设计时创建的,它们严格遵循ASP.Net页面生命周期,这意味着,在PreInit和Init事件后覆盖其状态,每个帖子中只更新txtDesignTextBox3
,因为其Text
属性在视图状态后更新 已设置(在Load
事件中)。
但是使用动态控件时,行为会有所不同,请记住MSDN说明:
对于在运行时添加的控件,Init和Load事件可能会在页面生命周期的后期发生
请考虑以下事项:
protected void Page_PreInit(object sender, EventArgs e)
{
var textBox = new TextBox { Text = "From PreInit", Width = new Unit("100%") };
textBox.Text += DateTime.Now.ToString();
this.myPlaceHolder.Controls.Add(textBox);
}
protected void Page_Init(object sender, EventArgs e)
{
var textBox = new TextBox { Text = "From Init", Width = new Unit("100%") };
textBox.Text += DateTime.Now.ToString();
this.myPlaceHolder.Controls.Add(textBox);
}
protected void Page_Load(object sender, EventArgs e)
{
var textBox = new TextBox { Text = "From Load", Width = new Unit("100%") };
textBox.Text += DateTime.Now.ToString();
this.myPlaceHolder.Controls.Add(textBox);
}
在这种情况下,控件的行为略有不同,在这种情况下,在每个帖子中,控件永远不会更新甚至不是Load
事件中创建的控件
原因是他们的生命周期事件发生在页面生命周期的后期,这意味着他们的状态被覆盖即使在Load事件之后
要解决此问题,您可以使用LoadComplete
事件,在这种情况下您可以更改动态控件的状态:
protected void Page_LoadComplete(object sender, EventArgs e)
{
var textBox = new TextBox { Text = "From LoadComplete", Width = new Unit("100%") };
textBox.Text += DateTime.Now.ToString();
this.myPlaceHolder.Controls.Add(textBox);
}
在这种情况下,状态将在每个帖子中更新。
但是,请注意您应该在LoadComplete
事件之前订阅动态控件事件,否则它们将不会被引发。
......我知道我讨厌这种行为,这就是我喜欢MVC的原因
作为在设计时创建的控件的快速参考:请注意LoadViewState
方法在PreInit
和Init
事件之后但在Load
之前调用 {1}}事件。 Load
事件被视为稳定,因为在此事件中您可以访问控件的视图状态。另请注意,RaisePostBackEvent
方法代表导致回发的控件事件,可以是SelectedIndexChanged
,Click
等,此事件在之后处理 Load
事件
有关完整的详细规范,请阅读the MSDN Page Life-Cycle documentation
答案 1 :(得分:1)
我经常看到这是由页面生命周期问题引起的。如果仅在触发事件时创建控件,那么当您的索引更改事件触发时,控件不存在以将其绑定到回发上。
示例:
您必须确保在.NET尝试处理事件之前创建下拉列表。
答案 2 :(得分:-4)
你错过了:
1-覆盖SaveViewState
2-覆盖LoadViewState
我提供了这个问题的示例代码。我测试一下这是工作。
ASPX:
<form id="form1" runat="server">
<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
<div id="myDiv" runat="server">
</div>
<asp:Label ID="lblDescription" runat="server"></asp:Label>
</form>
代码背后:
public partial class Default : System.Web.UI.Page
{
private List<string> values = new List<string>();
protected void Page_Load(object sender, EventArgs e)
{
}
protected override object SaveViewState()
{
object baseState = base.SaveViewState();
object[] allStates = new object[2];
allStates[0] = baseState;
allStates[1] = values;
return allStates;
}
protected override void LoadViewState(object savedState)
{
object[] myState = (object[])savedState;
if (myState[0] != null)
base.LoadViewState(myState[0]);
if (myState[1] != null)
{
values = (List<string>)myState[1];
MyRender();
}
}
protected void Button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < 10; i++)
{
DropDownList ddl = new DropDownList();
ddl.ID = "ClientID" + i;
ddl.Items.Add("Item 1");
ddl.Items.Add("Item 2");
ddl.AutoPostBack = true;
values.Add(ddl.SelectedValue);
myDiv.Controls.Add(ddl);
}
}
private void MyRender()
{
for (int i = 0; i < values.Count; i++)
{
DropDownList ddl = new DropDownList();
ddl.ID = "ClientID" + i;
ddl.Items.Add("Item 1");
ddl.Items.Add("Item 2");
ddl.AutoPostBack = true;
ddl.SelectedIndexChanged += new EventHandler(ddl_SelectedIndexChanged);
myDiv.Controls.Add(ddl);
}
}
void ddl_SelectedIndexChanged(object sender, EventArgs e)
{
lblDescription.Text = ((DropDownList)sender).ID + ": Selected Index Changed";
}
}