回发后文本框显示旧值,而数据库成功更新为新值

textbox shows old value after postback while database successfully update with new value

我有一个带有 radiobuttonlist 模板列和页脚中的 textbox 的 GridView。我希望单选按钮在选中时立即更新并使用本教程实现所需的功能 http://www.dotnetcurry.com/ShowArticle.aspx?ID=261。效果很好。

当页脚文本框中的新值更改时,SQL 通过 TextChanged() 事件中的 SqlDataSource Update() 成功更新,但旧值在回发后返回到文本框中。作为检查,我将新值传递给页面上的标签并且该标签也正确显示。

我尝试将 GridView1.DataBind() 放入 if(!IsPostBack) 的 Page_Load() 中,但这会导致单选按钮列表项目在更改时无法保持选中状态并且 sqldatasource 未更新。

我不知道这是否相关,但因为这个应用程序是原型,当用户在文本框中输入 MYID 并单击按钮时,我当前正在页面加载后在 gridview 中加载特定记录。最终,网格将加载通过来自另一个页面的 QueryString 提供的值。

本质上,我希望文本框像单选按钮列表一样工作...一旦更改值,我希望数据库在回发后更新并在 grid/textbx 中显示新值。有什么明显的我想念的吗?

UPDDATE:添加了radiobuttonlist selectedindexchanged事件代码 更新 2: 添加了 sqldatasource 更新 3: 解决方案是通过自定义方法直接更新 SQL 数据库,删除了 sqldatasource 中的第二个更新查询。更新了 TextChanged 事件代码并添加了自定义方法。

HTML:

<asp:GridView ID="GridView1" runat="server" 
        AutoGenerateColumns="False" 
        DataKeyNames="MYID" 
        DataSourceID="SqlDataSource1" 
        onrowdatabound="GridView1_RowDataBound" 
        ShowFooter="True" > 
        <Columns> 
<asp:BoundField DataField="MYID" HeaderText="MYID" ReadOnly="True" 
                SortExpression="MYID" /> 
            <asp:BoundField DataField="DocID" HeaderText="DocID" ReadOnly="True" 
                SortExpression="DocID" />
            <asp:BoundField DataField="ItemID" HeaderText="ItemID" 
                InsertVisible="False" ReadOnly="True" SortExpression="ItemID" />
            <asp:TemplateField HeaderText="Item" SortExpression="Item">
                <ItemTemplate>
                    <asp:Label ID="Label1" runat="server" Text='<%# Bind("Item") %>'></asp:Label>
                </ItemTemplate>
                <FooterTemplate > 
               <asp:TextBox ID="txtComment1" runat="server" 
                    Text='Section 1 Comments' AutoPostBack="True" 
                    ontextchanged="txtComment1_TextChanged" MaxLength="1000" 
                    TextMode="MultiLine" Width="650px"></asp:TextBox> 
            </FooterTemplate>
            </asp:TemplateField>
                <asp:TemplateField HeaderText=" -- 1 -- 2 -- 3 -- 4 -- 5 -- " >     
                    <ItemTemplate>
                <asp:RadioButtonList AutoPostBack="True" ID="rblRating" runat="server"
                    Enabled="true" SelectedIndex='<%#Convert.ToInt32(DataBinder.Eval(Container.DataItem , "Rating"))%>' 
                    OnSelectedIndexChanged="rblRating_SelectedIndexChanged" RepeatDirection="Horizontal">
                    <asp:ListItem Value="0">0</asp:ListItem>
                    <asp:ListItem Value="1">1</asp:ListItem>
                    <asp:ListItem Value="2">2</asp:ListItem>
                    <asp:ListItem Value="3">3</asp:ListItem>
                    <asp:ListItem Value="4">4</asp:ListItem>
                    <asp:ListItem Value="5">5</asp:ListItem>                        
                </asp:RadioButtonList>
            </ItemTemplate>

        </asp:TemplateField>
            <asp:BoundField DataField="Rating" HeaderText="Rating" 
                SortExpression="Rating" ReadOnly="True" />
        </Columns>
    </asp:GridView>
        <asp:Label ID="lblComments1" runat="server" Text="Label"></asp:Label>
    </div>

.CS:

protected void UpdateComment1(int myid, string comment)
        {                                                
            using (SqlConnection con = new SqlConnection(conStr)))
        { 
        string cmdStr = "UPDATE tblComments SET Comment1 = @Comment1 WHERE MYID = @MYID";

                using (SqlCommand cmd = new SqlCommand(cmdStr, con)))
                {  
                cmd.Parameters.AddWithValue("@MYID", myid);
                cmd.Parameters.AddWithValue("@Comment1", comment);
                try
                {
                    con.Open();
                    int affectedRows = cmd.ExecuteNonQuery();
                }
                catch (SqlException ex)
                {
                    Response.Write(ex.Message);
                }
        }
       }
        }
protected void txtComment1_TextChanged(object sender, EventArgs e)
        {
            TextBox tbox = (TextBox)sender;
            string oldComment1 = ViewState["OldComment1"].ToString(); //value saved from PreRender()
            string newComment1 = (GridView1.FooterRow.FindControl("txtComment1") as TextBox).Text;
            ViewState["Section1Comments"] = newComment1;

                if(oldComment1 != newComment1)
                {
                    //<<TODO>>update history table 
                }

            if (newComment1 != null)
            {   
             //update SQL directly via custom method                  
              UpdateComment1(Convert.ToInt32(MYID), newComment1);  
            }
            GridView1.DataBind(); 
        }

 protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            DataRowView drv = e.Row.DataItem as DataRowView;
            RadioButtonList rbtnl = (RadioButtonList)e.Row.FindControl("rblRating");

            if (e.Row.RowType == DataControlRowType.DataRow)
            {
                if ((e.Row.RowState & DataControlRowState.Normal) > 0) //.Edit, .Normal, .Alternate, .Selected
                {
             //check for null
                    if (rbtnl.SelectedItem != null)
                    {
                        if (rbtnl.SelectedItem.Text == "0") //if rating isn’t inserted into SQL yet, deselect all 5 radio buttons
                        {
                            rbtnl.SelectedItem.Selected = false;
                        }
                            rbtnl.SelectedValue = drv[4].ToString();
                    }
                }

                //remove extra list item 
                ListItem blank = rbtnl.Items.FindByValue("0");
                if (blank != null)
                {
                    rbtnl.Items.Remove(blank);//always remove list item at index zero
                }
            }
        }

protected void rblRating_SelectedIndexChanged(object sender, EventArgs e)
        {
            string rate = string.Empty;

            RadioButtonList rBtnList = (RadioButtonList)sender;
            GridViewRow gvr = (GridViewRow)rBtnList.Parent.Parent;

            if (rBtnList.SelectedValue != null)
            {
                rate = rBtnList.SelectedValue;

                SqlDataSource1.UpdateParameters["Rating"].DefaultValue = rate;
                SqlDataSource1.UpdateParameters["MYID"].DefaultValue = gvr.Cells[0].Text;
                SqlDataSource1.UpdateParameters["ItemID"].DefaultValue = gvr.Cells[2].Text;
            }
            else
            {     
            }  
            SqlDataSource1.Update(); 
            GridView1.DataBind();
        }

SQL & SqlDataSource:

    <asp:SqlDataSource 
    ID="SqlDataSource1" 
    runat="server" 
    ConnectionString="<%$ ConnectionStrings:SomeConnectionString %>" 
    SelectCommand="SelectSection1" 
    UpdateCommand="UPDATE tblDetails SET Rating = @Rating WHERE MYID =  @myid   AND ItemID = @ItemID;
    --UPDATE [tblComments]  SET [Comment1] = @Comment1 WHERE MYID =@myid; " 
    SelectCommandType="StoredProcedure" >
        <SelectParameters>
            <asp:ControlParameter ControlID="TextBox1" DefaultValue="0"              Name="eprid"  PropertyName="Text" Type="Int32" />
        </SelectParameters>
        <UpdateParameters> 
            <asp:Parameter Name="Rating" Type="Int32" /> 
            <asp:Parameter Name="myid" Type="Int32" /> 
            <asp:Parameter Name="ItemID" Type="Int32" /> 
            <asp:Parameter Name="Comment1" Type="String" />
            </UpdateParameters> 
</asp:SqlDataSource>

ALTER PROCEDURE [dbo].[SelectSection1] 
    @myid int  
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

--Has Form been submitted to tblComments yet?
declare @docid int
set @docid =(select distinct d.docid    
    from dbo.tblEmployee  e 
    full outer join dbo.tblDetails d on e.MYID = d.myid
    where e.myid = @myid)

 IF  @docid is null

----if not submitted yet, fill grid with evaluation items only, set rating to NULL
 BEGIN 
 SELECT 
      @myid As MYID
      ,0 as DocID
      ,ItemID 
      ,Item
      ,0 as Rating 
      ,'' As Comment1

  FROM [EPR].[dbo].[tblItems] 

  where SectionID = 1 and Active = 1  


  END
-- if submitted (DocID exists), fill grid with evaluations items and rating
 ELSE 
  BEGIN
  SELECT  
         d.eprid   
        ,d.DocID 
        ,i.[ItemID] 
        ,i.[Item] 
        ,d.Rating
        ,c.Comment1 

  FROM [EPR].[dbo].[tblItems] i

  join tblDetails  d on i.ItemID  = d.ItemID 
  join tblComments c on  d.MYID = c.MYID

  --Competence Section  
  where i.SectionID = 1 and i.Active = 1  and d.MYID = @myid 

  END
END

您正在尝试更新数据库并立即获取更新值,但 C# 代码没有等到 SQL 操作结束。请阅读:

How to requery updated values immediately after update procedure runs

我建议您单独更新更改的文本框代码。

//after all things done:
theTextbox.Text = the_value_that_it_sended.

我的解决方案包含在我更新的问题中。我的错误似乎是在 sqldatasource 中放置了 2 个更新查询。我删除了一个更新查询并创建了一个自定义方法来直接更新 SQL 数据库,让文本框在 textchanged 事件上立即更新,并在 selectedindexchanged 时让单选按钮列表立即更新。我读到如果用分号分隔每个查询,则可以使用 sqldatasource 进行 2 个 UPDATE 查询,但这在我的情况下不起作用。