JonV
JonV

Reputation: 523

Why is the asp:UpdatePanel not changing the value of my ASP:Textbox when the textbox is updated from Codebehind?

My scheme:

When the page is first loaded, all the controls are populated without issue.

The problem: When subsequent users are selected, ONLY the label value changes - NOT the textbox values.

What I've tried:

Is what I'm trying to do even possible - what am I missing?

Markup:

<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>

Codebehind:

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" ...
   }
}

Upvotes: 0

Views: 393

Answers (2)

JonV
JonV

Reputation: 523

The solution I'm going with is to add an Id along with ClientIDMode="AutoID" to the linkbutton controls. Additionally I added 'OnRowDataBound="gvContacts_RowDataBound" to the 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>

In the Code behind I removed the Timer_click method and added the below method which registers the 'AsyncPostBack' for selected controls.

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); 
  }
}  

Finally I added the Updatepanel .Update() call to the below method

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()
      }
   }
}

Upvotes: 1

wazz
wazz

Reputation: 5068

When you select a row, there's a postback. You said that initial values are set when the page loads, so that's what happens every time there's a postback.

If you have worked around that somehow, there is still a simpler solution, which is to use another data control, instead of single textboxes, etc.

You can use a DetailsView control with its own datasource control. The datasource control can get the data you need based on the ID of the row selected.

This is probably not 100% accurate but something like

<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>

With the right query, this will also help with editing the data, right in the detailsview control.

Upvotes: 1

Related Questions