回发后文本框显示旧值,而数据库成功更新为新值
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 查询,但这在我的情况下不起作用。
我有一个带有 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 查询,但这在我的情况下不起作用。