【发布时间】:2012-11-07 22:36:31
【问题描述】:
我继承了一些在 webpart 控件中具有 GridView 和 DetailsView 的代码。
DetailsView 能够创建两种不同类型的对象,例如A型和B型。
有一个按对象类型过滤 GridView 的下拉列表,DetailsView 有一个自动生成的插入按钮。
<asp:DetailsView ID="myDetailsView"
AutoGenerateInsertButton="True"
AutoGenerateEditButton="True"
AutoGenerateRows="false"
OnItemUpdating="OnItemUpdating"
DefaultMode="ReadOnly"
OnDataBound="OnDetailsViewBound"
OnItemInserting="OnItemInserting"
OnModeChanging="OnDetailsViewModeChanging"
runat="server">
我被要求:
- 移除 GridView 上的过滤器;和
- 将新建按钮/链接分成两部分,这样就有一个单独的按钮用于创建每种类型的对象。
删除过滤器意味着我需要一些其他方法来跟踪我们正在创建的对象类型。 我已通过将以上内容更改为:
<asp:DetailsView ID="myDetailsView"
AutoGenerateInsertButton="False"
AutoGenerateEditButton="True"
AutoGenerateRows="false"
OnItemUpdating="OnItemUpdating"
DefaultMode="ReadOnly"
OnDataBound="OnDetailsViewBound"
OnItemInserting="OnItemInserting"
OnModeChanging="OnDetailsViewModeChanging"
runat="server">
添加
<FooterTemplate>
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton runat="server" ID="lnkCreateNewTypeA" CommandName="New" CommandArgument="TypeA" CssClass="buttonlink">New Type A</asp:LinkButton>
<asp:LinkButton runat="server" ID="lnkCreateNewTypeB" CommandName="New" CommandArgument="TypeB" CssClass="buttonlink">New Type B</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</FooterTemplate>
我还没有删除过滤器,因此当前更改的功能与以前相同,因为我使用的是 New 命令。 我希望能够以某种方式捕获 New 事件,以便我可以将 CommandArgument 值放入隐藏字段,然后 DetailsView 将使用它来确定它正在创建的对象类型以及显示/隐藏字段。 当我在代码中的所有事件处理程序中放置断点时,第一个中断的是 OnDetailsViewModeChanging,它无法访问 CommandArgument。
OnItemCommand(如果它已连接)在 DetailsView 中的任何按钮被按下时触发并且确实让我可以访问 CommandArgument 但我不确定在此方法中究竟需要做什么来模拟事件链当您使用自动生成的按钮时会发生。
我唯一的选择是检索 CommandArgument 以在 OnItemCommand 事件处理程序中捕获它,还是在 New 命令上触发了一些其他事件?
谁能向我解释一下触发 New 命令时发生的事件顺序?
我在某处读到它将模式更改为插入,但我不知道它还能做什么。我相信在单击“插入”链接之前不会调用 OnItemInserting 方法。
任何帮助将不胜感激!
编辑:
我在 DetailsView 事件中找到了此链接,但它没有回答我的问题。 http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.detailsview_events.aspx
编辑:
我已尝试添加以下内容:
在 ascx 中:
<asp:DetailsView ID="myDetailsView"
...
OnItemCommand="OnItemCommand"
...
runat="server">
...
<asp:TemplateField HeaderText="Object Type" HeaderStyle-CssClass="columnHeader">
<ItemTemplate>
<asp:HiddenField runat="server" ID="hidObjectType" Value=""/>
<asp:Label runat="server" ID="lblObjectType"></asp:Label>
</ItemTemplate>
</asp:TemplateField>
在后面的代码中:
protected void OnItemCommand(object sender, DetailsViewCommandEventArgs e)
{
if (e.CommandName.Equals("New"))
{
var objectType = e.CommandArgument.ToString();
HiddenField typeHidden = this.myDetailsView.FindControl("hidObjectType") as HiddenField;
if (typeHidden != null)
{
typeHidden.Value = objectType;
}
Label typeLabel = this.myDetailsView.FindControl("lblObjectType") as Label;
if (typeLabel != null)
{
typeLabel.Text = objectType;
}
}
}
我发现我不需要在这个方法中设置模式(this.myDetailsView.ChangeMode(DetailsViewMode.Insert);),因为仍然触发了 OnDetailsViewModeChanging 事件处理程序。
这会找到控件并正确设置它们的值。如果我在 OnDetailsViewModeChanging 中再次检查这些值,它们的值仍会设置,但作为此方法中逻辑的一部分,会调用
this.myDetailsView.DataBind()
这会导致回发,此时值会丢失。我尝试添加
EnableViewState="True"
但这并没有什么不同。我已经查看了页面生命周期 (http://spazzarama.files.wordpress.com/2009/02/aspnet_page-control-life-cycle.pdf) 并认为 this.EnsureChildControls() 可能会有所帮助,但它也没有任何区别。
另一种方法是将值存储在会话中,但我不想这样做。
【问题讨论】:
标签: asp.net detailsview