【问题标题】:Save button does not work, when Update Panel is used使用更新面板时,保存按钮不起作用
【发布时间】:2012-08-07 10:45:03
【问题描述】:

我通过复制粘贴从下面的链接创建了一个批量可编辑的 gridview 网络用户控件 (BulkEditGridView.ascx),我没有包含任何外部代码:

http://blogs.msdn.com/b/mattdotson/archive/2005/11/09/real-world-gridview-bulk-editing.aspx

我将 BulkEditGridView 控件添加到另一个 Web 用户控件 OrderDetailGridView.ascx 并将数据源添加到 BulkEditGridView

我要做的是在我的 BulkEditGridView 中有一个相互依赖的下拉列表和 2 个文本框。 (见OrderDetailGridView.ascx源代码) 在下拉列表改变的那一刻,文本框保持不变,点击保存按钮后,相应的值更新并在文本框中可见。

但是我想做的是当下拉列表更改时,在单击保存按钮之前,我想在文本框中查看相应的值,然后能够使用保存按钮进行保存。

我尝试设置 autpostback=true 和 ddl_MaterialCode_SelectedIndexChanged 事件来更改文本框,但随后保存按钮不起作用,

我试着放了一个更新面板,还是一样,保存按钮不起作用。

以下是我的代码的源代码,其中保存按钮在单击保存后更新的文本框起作用。

BulkEditGridView.ascx 源代码(我自己没有添加任何东西,只是复制粘贴):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Exportal.Controls 
{
    public partial class BulkEditGridView : System.Web.UI.WebControls.GridView
    {


        private List<int> dirtyRows = new List<int>();

        [IDReferenceProperty(typeof(Control))]
        public string SaveButtonID
        {
            get
            {
                string val = (string)this.ViewState["SaveButtonID"];
                if (val == null)
                {
                    return string.Empty;
                }
                return val;
            }
            set
            {
                this.ViewState["SaveButtonID"] = value;
            }
        }

        protected override GridViewRow CreateRow(int rowIndex, int dataSourceIndex, DataControlRowType rowType, DataControlRowState rowState)
        {
            return base.CreateRow(rowIndex, dataSourceIndex, rowType, rowState | DataControlRowState.Edit);
        }

        protected override void OnLoad(EventArgs e)
        {

            base.OnLoad(e);

            //Attach an event handler to the save button.
            if (false == string.IsNullOrEmpty(this.SaveButtonID))
            {
                Control btn = RecursiveFindControl(this.NamingContainer, this.SaveButtonID);
                if (null != btn)
                {
                    if (btn is Button)
                    {
                        ((Button)btn).Click += new EventHandler(SaveClicked);
                    }
                }
            }

        }
        private void SaveClicked(object sender, EventArgs e)
        {
            this.Save();
            this.DataBind();
        }

        protected override void InitializeRow(GridViewRow row, DataControlField[] fields)
        {
            base.InitializeRow(row, fields);
            foreach (DataControlFieldCell cell in row.Cells)
            {
                if (cell.Controls.Count > 0)
                {
                    AddChangedHandlers(cell.Controls);
                }
            }
        }

        private void AddChangedHandlers(ControlCollection controls)
        {
            foreach (Control ctrl in controls)
            {
                if (ctrl is TextBox)
                {
                    ((TextBox)ctrl).TextChanged += new EventHandler(this.HandleRowChanged);
                }
                else if (ctrl is CheckBox)
                {
                    ((CheckBox)ctrl).CheckedChanged += new EventHandler(this.HandleRowChanged);
                }
                else if (ctrl is DropDownList)
                {
                    ((DropDownList)ctrl).SelectedIndexChanged += new EventHandler(this.HandleRowChanged);
                }
            }
        }

        void HandleRowChanged(object sender, EventArgs args)
        {
            GridViewRow row = ((Control)sender).NamingContainer as GridViewRow;
            if (null != row && !dirtyRows.Contains(row.RowIndex))
            {
                dirtyRows.Add(row.RowIndex);
            }
        }
        public void Save()
        {
            foreach (int row in dirtyRows)
            {
                this.UpdateRow(row, false);
            }

            dirtyRows.Clear();
        }
        private Control RecursiveFindControl(Control namingcontainer, string controlName)
        {
            Control c = namingcontainer.FindControl(controlName);

            if (c != null)
                return c;

            if (namingcontainer.NamingContainer != null)
                return RecursiveFindControl(namingcontainer.NamingContainer, controlName);

            return null;
        }
    }
}

OrderDetailGridView.ascx 源码:

<cc1:BulkEditGridView ID="BulkEditGridView1" runat="server" AutoGenerateColumns="False"
    DataKeyNames="RowNo" DataSourceID="SqlDataSource1" SaveButtonID="btn_Kaydet">
    <Columns>
        <asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
        <asp:BoundField DataField="PONumber" HeaderText="PONumber" SortExpression="PONumber" />
        <asp:TemplateField HeaderText="MaterialCode" SortExpression="MaterialCode">
            <EditItemTemplate>
                <asp:DropDownList ID="ddl_MaterialCode" runat="server" DataSourceID="SqlDataSource2"
                    DataTextField="MaterialCode" DataValueField="MaterialCode" SelectedValue='<%# Bind("MaterialCode") %>'
                    OnSelectedIndexChanged="ddl_MaterialCode_SelectedIndexChanged" >
                </asp:DropDownList>
            </EditItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="MaterialDescription" SortExpression="MaterialDescription">
            <EditItemTemplate>
                <asp:TextBox ID="txt_MaterialDescription" runat="server" Text='<%# Bind("MaterialDescription") %>'
                    Enabled="false"></asp:TextBox>
            </EditItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="MaterialCategory" SortExpression="MaterialCategory">
            <EditItemTemplate>
                <asp:TextBox ID="txt_MaterialCategory" runat="server" Text='<%# Bind("MaterialCategory") %>'
                    Enabled="false"></asp:TextBox>
            </EditItemTemplate>
        </asp:TemplateField>
        <asp:BoundField DataField="UnitOfMeasure" HeaderText="UnitOfMeasure" SortExpression="UnitOfMeasure" />
        <asp:BoundField DataField="Quantity" HeaderText="Quantity" SortExpression="Quantity" />
        <asp:BoundField DataField="ContainerType" HeaderText="ContainerType" SortExpression="ContainerType" />
        <asp:BoundField DataField="LoadingDate" HeaderText="LoadingDate" SortExpression="LoadingDate" />
    </Columns>
</cc1:BulkEditGridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:MyDbConn %>"
    DeleteCommand="DELETE FROM [OrderDetail] WHERE [RowNo] = @RowNo" InsertCommand="INSERT INTO [OrderDetail] ([FileNo], [PONumber], [MaterialCode], [MaterialDescription], [MaterialCategory], [UnitOfMeasure], [Quantity], [ContainerType], [LoadingDate]) VALUES (@FileNo, @PONumber, @MaterialCode, @MaterialDescription, @MaterialCategory, @UnitOfMeasure, @Quantity, @ContainerType, @LoadingDate)"
    SelectCommand="SELECT * FROM [OrderDetail]" UpdateCommand="UPDATE [OrderDetail] SET [FileNo] = @FileNo, [PONumber] = @PONumber, [MaterialCode] = @MaterialCode, [MaterialDescription] = @MaterialDescription, [MaterialCategory] = @MaterialCategory, [UnitOfMeasure] = @UnitOfMeasure, [Quantity] = @Quantity, [ContainerType] = @ContainerType, [LoadingDate] = @LoadingDate WHERE [RowNo] = @RowNo">
    <DeleteParameters>
        <asp:Parameter Name="RowNo" Type="Int32" />
    </DeleteParameters>
    <InsertParameters>
        <asp:Parameter Name="FileNo" Type="Int32" />
        <asp:Parameter Name="PONumber" Type="String" />
        <asp:Parameter Name="MaterialCode" Type="String" />
        <asp:Parameter Name="MaterialDescription" Type="String" />
        <asp:Parameter Name="MaterialCategory" Type="String" />
        <asp:Parameter Name="UnitOfMeasure" Type="String" />
        <asp:Parameter Name="Quantity" Type="Int32" />
        <asp:Parameter Name="ContainerType" Type="String" />
        <asp:Parameter Name="LoadingDate" Type="String" />
    </InsertParameters>
    <UpdateParameters>
        <asp:Parameter Name="FileNo" Type="Int32" />
        <asp:Parameter Name="PONumber" Type="String" />
        <asp:Parameter Name="MaterialCode" Type="String" />
        <asp:Parameter Name="MaterialDescription" Type="String" />
        <asp:Parameter Name="MaterialCategory" Type="String" />
        <asp:Parameter Name="UnitOfMeasure" Type="String" />
        <asp:Parameter Name="Quantity" Type="Int32" />
        <asp:Parameter Name="ContainerType" Type="String" />
        <asp:Parameter Name="LoadingDate" Type="String" />
        <asp:Parameter Name="RowNo" Type="Int32" />
    </UpdateParameters>
</asp:SqlDataSource>
<asp:SqlDataSource ID="SqlDataSource2" runat="server" ConnectionString="<%$ ConnectionStrings:MyDbConn %>"
    SelectCommand="SELECT [MaterialCode] FROM [Materials]"></asp:SqlDataSource>
<asp:Button ID="btn_Kaydet" runat="server" Text="Save" />

OrderDetailGridView.ascx.cs 源码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using SOrderDetailData;
using System.Data;

namespace Exportal.Controls
{
    public partial class OrderDetailGridView : System.Web.UI.UserControl
    {
        protected void ddl_MaterialCode_SelectedIndexChanged(object sender, EventArgs e)
        {

            DataTable dt = new DataTable();
            dt = OrderDetailData.GetMaterials();

            DropDownList ddl_MaterialCode = (DropDownList)sender;
            GridViewRow r = (GridViewRow)ddl_MaterialCode.Parent.Parent;

            TextBox txt_MaterialDescription = (TextBox)r.FindControl("txt_MaterialDescription");
            TextBox txt_MaterialCategory = (TextBox)r.FindControl("txt_MaterialCategory");            

            txt_MaterialDescription.Text = dt.Rows[ddl_MaterialCode.SelectedIndex]["MaterialDescription"].ToString();
            txt_MaterialCategory.Text = dt.Rows[ddl_MaterialCode.SelectedIndex]["MaterialCategory"].ToString();


        }
    }
}

【问题讨论】:

  • 你测试的是哪个浏览器?
  • 它在任何浏览器(例如IE8)中是否正常运行,还是在所有浏览器中都出现故障?
  • 创建一个相互依赖的下拉菜单和文本框不是问题,我在当前浏览器中使用常规 gridview 完成了该操作,问题在于上面 bulkeditgridview 的结构和保存按钮。
  • 我认为任何涉及更新面板的解决方案都将是次优且混乱的。最简单的方法是您可以使用 Ajax 保持交互客户端,也许是 with page methods

标签: c# asp.net ajax gridview updatepanel


【解决方案1】:

您可能需要坚持 List&lt;int&gt; dirtyRows 以便它可以在回帖中存活下来。我会推荐 CacheSession,但是请查看这篇 MSDN 文章 Nine Options for Managing Persistent User State in Your ASP.NET Application 了解所有可用选项。

【讨论】:

    【解决方案2】:

    您应该尝试两件事: 在下面的代码上放一个断点并调试。检查应用是否到达此 btn...

    if (null != btn) {
        if (btn is Button) {
            ((Button)btn).Click += new EventHandler(SaveClicked);
        }
    }
    

    验证后,您应该将此按钮添加到脚本管理器中

    if (null != btn) {
        if (btn is Button) {
            ((Button)btn).Click += new EventHandler(SaveClicked);
            ScriptManager.GetCurrent(Page).RegisterAsyncPostBackControl(btn);
        }
    }
    

    这个控件是否以某种方式位于更新面板中(也许您的母版页有一个用于所有内容的更新面板)?

    【讨论】:

      【解决方案3】:

      如果您只想使用下拉列表中的选定值填充文本框,我建议您使用 jquery...

      $('.dropdownclass').change(function() {
          $(this).closest('tr').find('.textboxclass').val($(this).val());
      });
      

      那么您就不必进行额外的回发,希望您的按钮点击会起作用。

      【讨论】:

        【解决方案4】:

        如果您只想使用下拉列表中的选定值填充文本框,我还建议您像以前写的那样使用 jquery...

        但如果您需要在下拉列表更改时执行更多操作...您需要使用网格的 RowCommand 事件。 这可能会帮助RowCommand

        短篇小说:

        1. 将 OnRowCommand="myGrid_RowCommand" 添加到网格的属性中
        2. 将 CommandName="ddlChanged" 添加到网格下拉菜单的属性中
        3. 如果您在网格的每一行中有超过 1 个命令,则 myGrid_RowCommand 函数应如下所示

          void myGrid_RowCommand(Object sender, GridViewCommandEventArgs e)  {    
          if(e.CommandName=="ddlChanged") 
              {// Do something
              } 
          if(e.CommandName == "ddl2Changed")
              {// Do something else
              }
          ...
          }
          

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-11-25
          • 2018-02-06
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多