我有一个ASP.NET页面,其中一个FormView数据绑定到一个ObjectDataSource,它使用动态生成的模板根据应用程序数据库中的布局信息呈现UI。我已经能够正确渲染模板,一切看起来都很好,直到我点击其中一个按钮来改变模式 - 没有任何改变。
我的代码基于以下文章/帖子中提供的解释:
http://www.codeproject.com/KB/aspnet/DynamicFormview.aspx
http://msdn.microsoft.com/en-us/library/ms227423.aspx
http://msdn.microsoft.com/en-us/library/y0h809ak(vs.71).aspx
简而言之,在Page.OnInit方法中,我将模板的实例分配给FormView EditItemTemplate,EmptyDataTemplate,InsertItemTemplate和ItemTemplate属性(每个属性的不同实例以及该模板的相应控件,布局等) 。我看到调用了与默认模式对应的模板的InstantiateIn方法,正确创建了控件层次结构,并按预期呈现了UI。
我的每个模板中都有一组按钮控件,用于启用模式切换。因此,例如,在ItemTemplate中,我有一个CommandName =“New”的按钮。我希望单击此按钮将导致FormView更改为插入模式。相反,我得到了回发,并在我的ItemTemplate上调用了InstantiateIn。我附加到FormView的ModeChanging和ModeChanged事件的处理程序不会触发。
当我单步执行控件层次结构时,我看到的对象模型与我在标记中创建的页面相同 - 只有一个例外。我使用HtmlTable,HtmlTableRow和HtmlTableCell控件来构造布局,而标记使用< table>,< tr>和< td>元件。
对我缺少什么的想法?我真的希望通过自动绑定(通过事件冒泡)来改变模式而不必手动创建和编码按钮及其操作。
以下是用于生成模板的代码:
public class FormViewTemplate : INamingContainer, ITemplate
{
private Boolean _childControlsCreated;
private Panel _panel;
public FormViewTemplate(TemplateMode mode) { Mode = mode; }
public TemplateMode Mode { get; private set; }
private void CreateChildControls()
{
_panel = new Panel();
_panel.Controls.Add(CreateButtons());
switch (Mode)
{
case TemplateMode.Edit:
_panel.Controls.Add(new LiteralControl("Edit Mode"));
break;
case TemplateMode.Empty:
_panel.Controls.Add(new LiteralControl("Empty Mode"));
break;
case TemplateMode.Insert:
_panel.Controls.Add(new LiteralControl("Insert Mode"));
break;
case TemplateMode.ReadOnly:
_panel.Controls.Add(new LiteralControl("Read-Only Mode"));
break;
}
}
private Panel CreateButtons()
{
var panel = new Panel();
var table = new HtmlTable()
{
Border = 0,
CellPadding = 2,
CellSpacing = 0
};
panel.Controls.Add(table);
var tr = new HtmlTableRow();
table.Rows.Add(tr);
var td = new HtmlTableCell();
tr.Cells.Add(td);
var addButton = new ASPxButton()
{
CommandName = "New",
Enabled = (Mode == TemplateMode.ReadOnly),
ID = "AddButton",
Text = "Add"
};
td.Controls.Add(addButton);
return panel;
}
private void EnsureChildControls()
{
if (!_childControlsCreated)
{
CreateChildControls();
_childControlsCreated = true;
}
}
void ITemplate.InstantiateIn(Control container)
{
EnsureChildControls();
container.Controls.Add(_panel);
}
}
(请注意,模板已缓存,因此控件层次结构仅构建一次。)