我正在构建一个动态按钮视图,它根据数据库中的项目数量以编程方式添加按钮。像一个简单的工作流引擎。在第一页调用时,事件处理程序按预期工作。将构建包含新项目的新页面并将其返回给客户端。在第二个回发时,不调用事件处理程序,并且视图保留相同的项目。通过重新单击相同的按钮(第三个回发),将触发事件处理程序中的断点。
我的问题是为什么即使我在每个帖子上重建页面(覆盖OnInit())也没有调用事件处理程序?
有关信息:方法LoadViewWithAlphabeticalDatasource()
和LoadViewWithWorkflowItem()
完全相同,因此我在下面的部分中删除了一个。事件以相同的方式添加。
代码:
<pre>
namespace EPS.Web.View.Article
{
public class DynamicGridView : BasePage, IDynamicGridView
{
protected override void OnInit(EventArgs e)
{
Presenter = new DynamicGridPresenter(this);
if (IsPostBack)
{
if (Presenter.Step smallerthan 2)
{
LoadViewWithAlphabeticalDatasource();
}
else
{
LoadViewWithWorkflowItem();
}
}
}
[PageMethod]
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
SetSubmenuVisible = false;
Presenter.InitView();
PrepareView();
}
AddEvents();
AddLabels();
PageMethodsEngine.InvokeMethod(this);
}
private void Back_Clicked(object sender, EventArgs e)
{
Presenter.StepEngine(DynamicGridPresenter.BACK, string.Empty, string.Empty);
PrepareView();
}
private void Cancel_Clicked(object sender, EventArgs e)
{
Presenter.StepEngine(DynamicGridPresenter.CANCEL, string.Empty, string.Empty);
PrepareView();
}
private void ForwardString(object sender, EventArgs e)
{
Presenter.StepEngine(DynamicGridPresenter.FORWARD, ((LinkButton)sender).CommandArgument, string.Empty);
PrepareView();
}
private void ForwardWorkflowItem(object sender, EventArgs e)
{
Presenter.StepEngine(DynamicGridPresenter.FORWARD, string.Empty, ((LinkButton)sender).CommandArgument);
PrepareView();
}
protected void PrepareView()
{
phDynamicGridView.Controls.Clear();
if (Presenter.Step smallerthan 2)
{
LoadViewWithAlphabeticalDatasource();
}
else
{
LoadViewWithWorkflowItem();
}
}
private void LoadViewWithWorkflowItem()
{
var table = new HtmlTable();
table.Attributes.Add("class", "tableDynamicGrid");
int max = GetRowLength(WODatasource.Count);
int temp = 1;
int actualPosition = 0;
int itr = 1;
var tr = new HtmlTableRow();
if (WODatasource.Count == 0)
{
phDynamicGridView.Controls.Add(new HtmlTable());
return;
}
foreach (WorkflowItem s in WODatasource)
{
if (actualPosition biggerOrEqual MaxLength && temp smallerOrEqual max)
{
table.Rows.Add(tr);
actualPosition = 0;
temp++;
tr = new HtmlTableRow();
}
actualPosition++;
var cell = new HtmlTableCell();
// cell.Attributes.Add("class", "cellDynamicGrid");
var btn = new LinkButton
{
CommandArgument = s.Oid.ToString(),
Text = s.SelectionItem.Name /*, CssClass = "linkButtonDynamicGrid"*/
};
btn.Click += ForwardWorkflowItem;
cell.Controls.Add(btn);
tr.Cells.Add(cell);
if (itr == WODatasource.Count && temp smallerOrEqual max)
{
while (itr biggerOrEqual WODatasource.Count && itr smallerThan max*MaxLength)
{
tr.Cells.Add(new HtmlTableCell());
itr++;
}
table.Rows.Add(tr);
phDynamicGridView.Controls.Add(table);
return;
}
itr++;
}
}
}
</pre>
答案 0 :(得分:4)
OnInit在调用 LoadPostData之前发生,这就是它在第二次点击时工作的原因。实际发生的是您正在处理先前回发的事件。
这是来自Asp.net 1.1的事件的简化版本; 2.0中间插入了一些额外的事件,比如OnPreInit。但订单仍然存在。
您必须使用Load或更高版本中的事件。有些人选择PreRender,但DataBinding的约定是加载。
<强>更新强>
我看到你正在动态地向控件树添加控件。这充满了陷阱(但完全可行。)
a)确保在页面加载时添加动态控件,而不仅仅是在回发时。 Postback / viewstate持久存在STATE(即数据),而不是对象。你应该在OnInit中添加它们(OnLoad也适用,但维护起来比较麻烦)。您目前只在回发时添加,这就是为什么第二次回发有效(而不是第一次)
b)只在初始化动态控件ONCE,就像在任何其他控件上一样 - 在[!IsPostBack]中加载。
-Oisin
答案 1 :(得分:3)
感谢大家帮助我。我找到了解决方案:
我不知道动态创建的按钮需要ID值。我建议Asp知道按钮是否已创建。不幸的是我错了。似乎.NET比较按钮上的ID而不是ControlTree中的位置。
我添加了
new Button{ID = itr.ToString()}
现在,当服务器重建站点时,会触发事件处理程序。
问候 X
答案 2 :(得分:1)
此类问题几乎总是将事件处理程序连接到页面生命周期中的错误位置。
答案 3 :(得分:0)
我遇到了类似的问题。我尝试了很多解决方案,但最后我注意到我的webform上的一个文本框正在回发到服务器,这搞砸了。这是一个难以捉摸的错误,因为我不是故意让我的文本框那样做。
答案 4 :(得分:0)
如果您使用ID变量而没有声明,这可能是问题所在。更改您的ID变量名称的名称。