DetailsView:如何在New命令上使用CommandArgument设置HiddenField值?

时间:2012-11-07 22:36:32

标签: asp.net detailsview

我继承了一些在webpart控件中有GridView和DetailsView的代码。

DetailsView能够创建两种不同类型的对象,例如TypeA和TypeB。

有一个下拉列表,按对象类型过滤GridView,DetailsView有一个自动生成的Insert按钮。

<asp:DetailsView ID="myDetailsView"  
    AutoGenerateInsertButton="True"
    AutoGenerateEditButton="True" 
    AutoGenerateRows="false" 
    OnItemUpdating="OnItemUpdating"
    DefaultMode="ReadOnly" 
    OnDataBound="OnDetailsViewBound"
    OnItemInserting="OnItemInserting" 
    OnModeChanging="OnDetailsViewModeChanging"        
    runat="server">

我被要求:

  1. 删除GridView上的过滤器;和
  2. 将New按钮/链接拆分为两个,这样就可以创建一个单独的按钮来创建每种类型的对象。
  3. 删除过滤器意味着我需要一些其他方法来跟踪我们正在创建的对象类型。 我通过将上面的内容更改为:

    来拆分新链接
    <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。

    当按下DetailsView中的任何按钮时,触发OnItemCommand(如果它已连接)并且确实允许我访问CommandArgument但是我不确定在此方法中到底需要做什么模仿使用自动生成的按钮时发生的事件链。

    我唯一的选择是检索CommandArgument以在OnItemCommand事件处理程序中捕获它还是在New命令上触发了一些其他事件?

    有人可以向我解释触发New命令时发生的事件顺序吗?

    我在某处读到它将模式更改为Insert但我不知道它还做了什么。我相信OnItemInserting方法不会被调用,直到&#34; Insert&#34;单击链接。

    感谢任何帮助!!


    修改

    我在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()可能会有所帮助但是#&# 39; s也没有区别。

    另一种方法是将值存储在会话中,但我不是。

1 个答案:

答案 0 :(得分:0)

据我所知,除了捕获所有命令的OnItemCommand之外,没有捕获“新”命令的事件。 (注意:您需要确保在LinkBut​​ton上设置了CausesValidation="False",否则代码不会分成OnItemCommand)。

单步执行代码时,会发生以下情况:

  1. 按下链接按钮后,触发OnItemCommand。 CommandName =“New”,在这里我可以检索CommandArgument
  2. 下一个OnModeChanging被触发。 e.NewMode =“插入”。从我看过的所有例子中,你在DetailsView上调用ChangeMode,然后在其上调用Databind()
  3. 下一个OnDataBound是由于调用Databind()
  4. 而触发的

    我没有找到在各种事件之间保留隐藏变量值的方法,因此我最终使用了会话变量。如果有人想要,代码如下。

    ASCX中的DetailsView声明:

        <asp:DetailsView ID="myDetailsView"  
            AutoGenerateInsertButton="False"
            AutoGenerateEditButton="True" 
            AutoGenerateRows="false" 
            OnItemInserting="OnItemInserting" 
            OnItemUpdating="OnItemUpdating"
            OnItemCommand="OnItemCommand"
            DefaultMode="ReadOnly" 
            OnDataBound="OnDetailsViewBound"
            OnModeChanging="OnDetailsViewModeChanging"        
            runat="server">
    

    在代码隐藏中:

    不断声明......

        private const string SESSIONKEY_MYVALUE = "MyValue";
        private const string DEFAULT_OBJECTTYPE = "TypeA";
    

    OnItemCommand事件处理程序......

        protected void OnItemCommand(object sender, DetailsViewCommandEventArgs e)
        {
            if (e.CommandName.Equals("New", StringComparison.InvariantCultureIgnoreCase))
            {
                var objectType = e.CommandArgument.ToString();
    
                HiddenField typeHidden = this.myDetailsView.FindControl("hidObjectType") as HiddenField;
                if (typeHidden != null)
                {
                    typeHidden.Value = objectType;
                }
    
                HttpContext.Current.Session[SESSIONKEY_MYVALUE] = objectType;
            }
        }
    

    OnModeChanging事件处理程序....

        protected void OnDetailsViewModeChanging(Object sender, DetailsViewModeEventArgs e)
        {
            if (e.NewMode == DetailsViewMode.Insert)
            {
                this.myDetailsView.ChangeMode(DetailsViewMode.Insert);
                this.myDetailsView.DataBind();
            }
        }
    

    OnDataBound事件处理程序...

        protected void OnDetailsViewBound(object sender, EventArgs e)
        {
            if (this.myDetailsView.CurrentMode == DetailsViewMode.Insert)
            {
                var sessionVar = HttpContext.Current.Session[SESSIONKEY_MYVALUE];
                var objectType = sessionVar == null ? 
                    DEFAULT_OBJECTTYPE : 
                    sessionVar.ToString();
    
                var typeHidden = this.myDetailsView.FindControl("hidObjectType") as HiddenField;
    
                if (typeHidden != null)
                {
                    typeHidden.Value = objectType;
                }
            }
        }