我遇到问题,事件处理程序总是在HiddenFields上触发,尽管我没有对该字段进行任何更改。
我有一个ASCX用户控件,我静态地声明了一些元素:
MyControl.ascx:
<div id="AnItem" runat="server">
<asp:Textbox id="TextBox1" runat="server" />
<asp:HiddenField id="HiddenField1" runat="server" />
</div>
(显然还有更多,但这是注释的标记)
MyControl.ascx.cs:
protected override void OnInit(EventArgs e){
base.OnInit(e);
if (SelectedValue != null){
TextBox1.Text = SelectedValue.Text;
HiddenField1.Value = SelectedValue.ID.ToString();
}
}
protected override void OnLoad(EventArgs e){
base.OnLoad(e);
if (String.IsNullOrEmpty(TextBox1.Text))
TextBox1.Attributes["style"] = "display:none";
TextBox1.TextChanged += ItemTouched;
HiddenField1.ValueChanged += ItemTouched;
}
protected void ItemTouched(object sender, EventArgs e){
// process changed values
}
代码似乎不合常规,因为我已经省略了与我的问题无关的项目(我假设)。
我的控件实际上是使用我可以序列化的包装类动态创建的:
[Serializable]
public class ListControl{
public void GenerateControl(TemplateControl parent){
var control = parent.LoadControl("~/MyControl.ascx") as MyControl;
control.Options = _options;
control.SelectedValue = _selectedValue;
return control;
}
private IList<SelectableOption> _options;
private SelectionOption _selectedValue;
}
(这个包装器的原因是由于一个大的遗留代码库在创建可选值列表时太慢了._options列表生成一次然后保存在会话中以加快回发执行。)
ItemTouched附加到用户可能触摸(或由JavaScript操纵)的每个元素。我的问题是它在每次回发时被触发 - 即使在客户端没有修改HiddenField1(我已经通过移除所有触及它的JavaScript来证实这一点)。
我不知道处理程序被解雇的原因是没有触及值。当没有设置控制值时(例如在我的OnInit方法中),它不会触发,但如果它们是“预先设置”的话,它总是会触发。如果在设置默认值后附加事件处理程序,我不希望更改处理程序触发,但似乎并非如此。我是否对ASP.NET事件做了一个根本错误的假设?
答案 0 :(得分:1)
已经有一段时间了,但是如果我没记错的话,HiddenField或Textbox控件会根据将当前值与ViewState中存储的值进行比较来触发ValueChanged。由于你是动态创建这些控件,我猜他们的viewstate没有正确地(或足够早)重新水化 - 然后触发ValueChanged事件处理程序触发(因为它们的值与ViewState中存储的值不同) 。
真正了解正在发生的事情的最佳方法是在.NET Framework上启用调试:http://msdn.microsoft.com/en-us/library/cc667410.aspx并在触发ValueChanged的区域周围设置一些断点。然后你可以看到导致它的条件,这应该有助于你弄清楚如何解决它。