我有一个 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);
}
}
(请注意,模板已缓存,因此控制层次结构仅构建一次。)