当从 Codebehind 更新文本框时,为啥 asp:UpdatePanel 不改变我的 ASP:Textbox 的值?

Posted

技术标签:

【中文标题】当从 Codebehind 更新文本框时,为啥 asp:UpdatePanel 不改变我的 ASP:Textbox 的值?【英文标题】:Why is the asp:UpdatePanel not changing the value of my ASP:Textbox when the textbox is updated from Codebehind?当从 Codebehind 更新文本框时,为什么 asp:UpdatePanel 不改变我的 ASP:Textbox 的值? 【发布时间】:2021-11-02 01:35:24 【问题描述】:

我的方案:

我有一个标签以及一些在 asp:Updatepanel 中加载的文本框。这些控件最初加载了 SQL 数据库中的值。这些值基于传递给页面的初始索引。 此外,该页面还包含一个 gridview,其中包含“联系人”列表。 这个想法是,如果用户从gridview 中选择了一个联系人,该索引用于重新查询SQL db。此函数返回一个数据表,用于使用选定的联系人数据(姓名、地址、电子邮件等)填充上述文本框。然后用户可以根据需要修改文本框。 目前,我正在使用 asp:timer 在选择其他联系人时触发更新面板(尽管我欢迎更优雅的触发解决方案)。

第一次加载页面时,所有控件都被填充而没有问题。

问题: 选择后续用户时,仅更改标签值 - 而不是文本框值。

我尝试过的:

如果我禁用计时器/触发器,那么当在 gridview 中选择记录时,即使标签也不会更新。这似乎表明计时器/触发器作为 AsyncPostBackTrigger 是有效的(启用时)。 对于文本框,我尝试了如何分配文本框值的变体(例如 Textboxt1.text = value; TextBox1.Attributes.Add("value", value1); 除了使用 asp:Textbox 之外,我还尝试使用:

我正在尝试做的事情是否可能 - 我错过了什么?

标记:

<asp:Timer runat="server" ID="Timer1" Interval="400" Enabled="false" OnTick="ContactsTimer_Tick" />
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional" >  
   <ContentTemplate>
      <asp:Label ID="lblContactAccountID" runat="server"/>
      <asp:TextBox ID="txtContactFirstName" runat="server"/> 
      <%--edit: also tried:
      <input type="text"  id="txtContactFirstName" runat="server" />--%>
   </ContentTemplate>
   <Triggers>
      <asp:AsyncPostBackTrigger ControlID="ContactsTimer" EventName="Tick" />
   </Triggers>
</asp:UpdatePanel>

<asp:GridView ID="gvContacts" runat="server" CssClass="table table-striped solid-top" AutoGenerateColumns="false"
   DataKeyNames="PersonID" OnRowCommand="gvContacts_RowSelected">
   <Columns>
      <asp:BoundField DataField="PersonID" />
      <asp:TemplateField HeaderText="Name" ItemStyle-Width="10%" ItemStyle-HorizontalAlign="Center">
         <ItemTemplate>
            <asp:LinkButton runat="server" CommandName="Selected" CommandArgument="<%# Container.DataItemIndex %>"><%#Eval("LastName")%></asp:LinkButton>
            <asp:LinkButton runat="server" CommandName="Selected" CommandArgument="<%# Container.DataItemIndex %>"><%#Eval("FirstName")%></asp:LinkButton>
         </ItemTemplate>
      </asp:TemplateField>
      <asp:TemplateField HeaderText="Action" ItemStyle-Width="10%" ItemStyle-HorizontalAlign="Center">
         <ItemTemplate>
            <asp:ImageButton runat="server" ImageUrl="~/Images/icon_pencil.png" ToolTip='<%# "Edit Profile for "  + Eval("firstname") + " " + Eval("lastname") %>' CommandName="Edit" CommandArgument="<%# Container.DataItemIndex %>" />
         </ItemTemplate>
      </asp:TemplateField>
   </Columns>
</asp:GridView>

代码隐藏:

private void LoadSelectedContact(int personID)

   DataTable dt = GetProfileContacts(personID, true);
   if (dt.Rows.Count > 0)
   
      foreach (DataRow row in dt.Rows)
      
         lblContactAccountID.Text = row["PersonID"].ToString();
         txtContactFirstName.Text = row["FirstName"].ToString();

         // edit: also tried the below without success
         //            string FirstName = row["FirstName"].ToString();
         //            txtContactFirstName.value= FirstName;
         //            txtContactFirstName.Attributes.Add("value", FirstName);


         // ...
         ContactsTimer.Enabled = true;
      
   


protected void ContactsTimer_Tick(object sender, EventArgs e)

   ContactsTimer.Enabled = false;
   upnlContacts.Update();


protected void gvContacts_RowSelected(object sender, GridViewCommandEventArgs e)

   GridViewRow row;
   if (e.CommandSource.ToString() == "System.Web.UI.WebControls.ImageButton")
   
      row = (GridViewRow)((ImageButton)e.CommandSource).NamingContainer;
   
   else
   
      row = (GridViewRow)((LinkButton)e.CommandSource).NamingContainer;
   
   int personID = Int32.Parse(row.Cells[0].Text);
   switch (e.CommandName)
   
      case "Selected":
         LoadSelectedContact(personID);
         break;
      //case "Edit" ...
   

【问题讨论】:

【参考方案1】:

当您选择一行时,会有一个回发。您说初始值是在页面加载时设置的,所以每次回发时都会发生这种情况。

如果您以某种方式解决了这个问题,还有一个更简单的解决方案,即使用另一个数据控件,而不是单个文本框等。

您可以将 DetailsView 控件与它自己的数据源控件一起使用。数据源控件可以根据所选行的ID获取你需要的数据。

这可能不是 100% 准确,但类似于

<asp:SqlDataSource ID="dsPersonDetails" runat="server" DataFile="~/App_Data/etc"
    SelectCommand="SELECT * FROM MyTable WHERE PersonID = ?">
    <SelectParameters>
        <asp:ControlParameter ControlID="gvContacts" Name="PersonID"
            PropertyName="SelectedValue" Type="Int32" />
    </SelectParameters>
</asp:SqlDataSource>

使用正确的查询,这也将有助于在 detailsview 控件中编辑数据。

【讨论】:

【参考方案2】:

我要使用的解决方案是将 Id 与 ClientIDMode="AutoID" 一起添加到链接按钮控件。 此外,我将 'OnRowDataBound="gvContacts_RowDataBound" 添加到 Asp:DataGrid:

<asp:ScriptManager ID="ScriptManager1" runat="server" />
<asp:GridView ID="gvContacts" runat="server" .... OnRowDataBound="gvContacts_RowDataBound">
        ....
        <asp:TemplateField HeaderText="Name" >
                 <ItemTemplate>
                    <asp:LinkButton id="lnkLastName" ClientIDMode="AutoID"
        runat="server" CommandName="Selected" CommandArgument="<%# Container.DataItemIndex %>"><%#Eval("LastName")%></asp:LinkButton>
                    <asp:LinkButton id="lnkFirstName" ClientIDMode="AutoID"
        runat="server" CommandName="Selected" CommandArgument="<%# Container.DataItemIndex %>"><%#Eval("FirstName")%></asp:LinkButton>
                 </ItemTemplate>
              </asp:TemplateField>

在后面的代码中,我删除了 Timer_click 方法并添加了以下方法,该方法为选定的控件注册了“AsyncPostBack”。

protected void gvContacts_RowDataBound(object sender, GridViewRowEventArgs e) 
 
  if (e.Row.RowType == DataControlRowType.DataRow) 
   LinkButton lnk;

   lnk= e.Row.FindControl("lnkFirstName") as LinkButton; 
   ScriptManager.GetCurrent(this).RegisterAsyncPostBackControl(lnk); 

   lnk = e.Row.FindControl("lnkLastName") as LinkButton; 
   ScriptManager.GetCurrent(this).RegisterAsyncPostBackControl(lnk); 
  
  

最后我在下面的方法中添加了 Updatepanel .Update() 调用

private void LoadSelectedContact(int personID)

   DataTable dt = GetProfileContacts(personID, true);
   if (dt.Rows.Count > 0)
   
      foreach (DataRow row in dt.Rows)
      
         lblContactAccountID.Text = row["PersonID"].ToString();
         txtContactFirstName.Text = row["FirstName"].ToString();
         // ...
         upnlContacts.Update()
      
   

【讨论】:

我打算在 UpdatePanel 上提到 .Update() 方法,但我忘了。很高兴你找到了它。

以上是关于当从 Codebehind 更新文本框时,为啥 asp:UpdatePanel 不改变我的 ASP:Textbox 的值?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我收到错误“Microsoft Visual Studio 2012 已停止工作”(当我单击文本框时)[关闭]

为啥当从派生类访问基类的数据时它会返回废话(我认为是指针数据)

为啥在附加熊猫数据框时列顺序会发生变化?

asp.net mvc c# - 是不是可以从 CodeBehind 中的模型访问视图中文本框的值?

在 ASP.NET 的 CodeBehind 中添加和删除“is-invalid”类

为啥在读取数据框时我的列名中出现 X.?