0

I have a html table on a page:

<table id="tblMain" runat="server" style="margin-left: auto; margin-right: auto;">
    <tr>
        <td>
            Safety
        </td>
        <td>
            <asp:TextBox ID="txtSafety" Width="400px" ReadOnly="true" TextMode="MultiLine" runat="server"></asp:TextBox>
        </td>
        <td>
            <asp:Button ID="btnSafety" runat="server" Width="150px" Text="Edit" 
                OnClick="Edit_Text" CommandArgument="0" />
        </td>
    </tr>
    <tr>
        <td>
            Environment
        </td>
        <td>
            <asp:TextBox ID="txtEnvironment" Width="400px" ReadOnly="true" TextMode="MultiLine" runat="server"></asp:TextBox>
        </td>
        <td>
            <asp:Button ID="bntEnvironment" Width="150px" runat="server" Text="Edit" 
                OnClick="Edit_Text" CommandArgument="1" />
        </td>
    </tr>
    <tr>
        <td>
            Quality
        </td>
        <td>
            <asp:TextBox ID="txtQuality" Width="400px" ReadOnly="true" TextMode="MultiLine" runat="server"></asp:TextBox>
        </td>
        <td>
            <asp:Button ID="btnQuality" Width="150px" runat="server" Text="Edit" 
                OnClick="Edit_Text" CommandArgument="2" />
        </td>
    </tr>
    <tr>
        <td>
            Ferrous System
        </td>
        <td>
            <asp:TextBox ID="txtFerrousSystem" Width="400px" ReadOnly="true" TextMode="MultiLine"
                runat="server"></asp:TextBox>
        </td>
        <td>
            <asp:Button ID="btnFerrousSystem" Width="150px" runat="server" Text="Edit" 
                OnClick="Edit_Text" CommandArgument="3" />
        </td>
    </tr>
    <tr>
        <td>
            Coke System
        </td>
        <td>
            <asp:TextBox ID="txtCokeSystem" Width="400px" ReadOnly="true" TextMode="MultiLine"
                runat="server"></asp:TextBox>
        </td>
        <td>
            <asp:Button ID="btnCokeSystem" Width="150px" runat="server" Text="Edit" 
                OnClick="Edit_Text" CommandArgument="4" />
        </td>
    </tr>
    <tr>
        <td>
            Coal Yards
        </td>
        <td>
            <asp:TextBox ID="txtCoalYards" Width="400px" ReadOnly="true" TextMode="MultiLine"
                runat="server"></asp:TextBox>
        </td>
        <td>
            <asp:Button ID="btnCoalYards" Width="150px" runat="server" Text="Edit" 
                OnClick="Edit_Text" CommandArgument="5" />
        </td>
    </tr>
    <tr>
        <td>
            Screenhouse
        </td>
        <td>
            <asp:TextBox ID="txtScreenhouse" Width="400px" ReadOnly="true" TextMode="MultiLine"
                runat="server"></asp:TextBox>
        </td>
        <td>
            <asp:Button ID="btnScreenhouse" Width="150px" runat="server" Text="Edit" 
                OnClick="Edit_Text" CommandArgument="6" />
        </td>
    </tr>
    <tr>
        <td>
            Process Plant
        </td>
        <td>
            <asp:TextBox ID="txtProcessPlant" Width="400px" ReadOnly="true" TextMode="MultiLine"
                runat="server"></asp:TextBox>
        </td>
        <td>
            <asp:Button ID="btnProcessPlant" Width="150px" runat="server" Text="Edit" 
                OnClick="Edit_Text" CommandArgument="7" />
        </td>
    </tr>
    <tr>
        <td>
            New Mill
        </td>
        <td>
            <asp:TextBox ID="txtNewMill" Width="400px" ReadOnly="true" TextMode="MultiLine" runat="server"></asp:TextBox>
        </td>
        <td>
            <asp:Button ID="btnNewMill" Width="150px" runat="server" Text="Edit" 
                OnClick="Edit_Text" CommandArgument="8" />
        </td>
    </tr>
    <tr>
        <td>
            Streamphases
        </td>
        <td>
            <asp:TextBox ID="txtStreamphases" Width="400px" ReadOnly="true" TextMode="MultiLine"
                runat="server"></asp:TextBox>
        </td>
        <td>
            <asp:Button ID="btnStreamphases" Width="150px" runat="server" Text="Edit" 
                OnClick="Edit_Text" CommandArgument="9" />
        </td>
    </tr>
    <tr>
        <td>
            Furnace Silos Injection
        </td>
        <td>
            <asp:TextBox ID="txtFurnaceSilosInjection" Width="400px" ReadOnly="true" TextMode="MultiLine"
                runat="server"></asp:TextBox>
        </td>
        <td>
            <asp:Button ID="btnFurnaceSilosInjection" Width="150px" runat="server" Text="Edit"
                OnClick="Edit_Text" CommandArgument="10" />
        </td>
    </tr>
    <tr>
        <td>
            CompressedAir
        </td>
        <td>
            <asp:TextBox ID="txtCompressedAir" Width="400px" ReadOnly="true" TextMode="MultiLine"
                runat="server"></asp:TextBox>
        </td>
        <td>
            <asp:Button ID="btnCompressedAir" Width="150px" runat="server" Text="Edit" 
                OnClick="Edit_Text" CommandArgument="11" />
        </td>
    </tr>
    <tr>
        <td>
            Planned Maintenance
        </td>
        <td>
            <asp:TextBox ID="txtPlannedMaintenance" Width="400px" ReadOnly="true" TextMode="MultiLine"
                runat="server"></asp:TextBox>
        </td>
        <td>
            <asp:Button ID="btnPlannedMaintenance" Width="150px" runat="server" Text="Edit" 
                OnClick="Edit_Text" CommandArgument="12" />
        </td>
    </tr>
    <tr>
        <td>
            Notifications Raised
        </td>
        <td>
            <asp:TextBox ID="txtNotificationsRaised" Width="400px" ReadOnly="true" TextMode="MultiLine"
                runat="server"></asp:TextBox>
        </td>
        <td>
            <asp:Button ID="btnNotificationsRaised" Width="150px" runat="server" Text="Edit"
                OnClick="Edit_Text" CommandArgument="13" />
        </td>
    </tr>
    <tr>
        <td>
            Manning
        </td>
        <td>
            <asp:TextBox ID="txtManning" Width="400px" ReadOnly="true" TextMode="MultiLine" runat="server"></asp:TextBox>
        </td>
        <td>
            <asp:Button ID="btnManning" Width="150px" runat="server" Text="Edit" 
                OnClick="Edit_Text" CommandArgument="14" />
        </td>
    </tr>
    <tr>
        <td>
            ShiftHandover
        </td>
        <td>
            <asp:TextBox ID="txtShiftHandover" Width="400px" ReadOnly="true" TextMode="MultiLine"
                runat="server" OnClick="Edit_Text"></asp:TextBox>
        </td>
        <td>
            <asp:Button ID="btnShiftHandover" Width="150px" runat="server" Text="Edit" 
                OnClick="Edit_Text" CommandArgument="15" />
        </td>
    </tr>
</table>

When the button is pressed the following method is called:

protected void Edit_Text(object sender, EventArgs e)
{
    Button btn = sender as Button;
    if (btn != null)
    {
        editField = btn.ID.Replace("btn", "");
        btn.Visible = false;
        //Getting and storing rowindex

        TextBox txt = this.FindControl("txt" + editField) as TextBox;
        txt.ReadOnly = false;
        txt.BackColor = System.Drawing.ColorTranslator.FromHtml("#FFFFB2");
        txt.Focus();
        comment = txt.Text;
        //Further methods unnecessary for this question
    }
}

As you can see, the prefix is stripped from the controls and then added in when necessary to find the right control at the point, therefore the string for the FindControl method is correct and should return a a TextBox.

However, by stepping through I can see that it is passing an empty TextBox instance rather than the expected result or a null.

I have already tried the findcontrol function on the table itself, I used 'this' as a second check but both yielded the same results.


I suspect the html table is a problem as in another method I am having issues finding a button manually in the html table:

Button editbtn = tblMain.Rows[GetRowIndex(hdnRowIndex.Value)].Cells[2].Controls[0] as Button;

Which is returning a null despite there always being a cell button in that cell for each row

EDIT - Here is the binding that is performed

private void bindData(DataTable dt)
{
    if (dt.Rows.Count > 0)
    {
        foreach (DataColumn col in dt.Columns)
        {
            TextBox txt = tblMain.FindControl("txt" + col.ColumnName) as TextBox;
            if (txt != null)
            {
                txt.Text = dt.Rows[0][col].ToString();
            }
        }
    }
}
nickson104
  • 580
  • 1
  • 7
  • 18
  • Your table isn't generated via some sort of DataBound control like a GridView, Repeater, or a ListView, is it? – j.f. May 14 '15 at 12:43
  • couldn't you use the `object sender` as Button ? – leAthlon May 14 '15 at 12:46
  • No it is a html table, each row being similar to the one shown. There is data being bound to it, but that is being done to each textbox in turn by looping a datatable and establishing the textbox from the field name. I shall append it to the question – nickson104 May 14 '15 at 12:48
  • So your button is null? Or the text box? Title suggest the former but description says the latter – Andrei May 14 '15 at 12:48
  • i see the confusion, sorry Andrei, i made a typo and wrote button instead of textbox in the middle of the question. I shal ledit – nickson104 May 14 '15 at 12:53

2 Answers2

1

Your problem is here:

this.FindControl("txt" + editField) as TextBox;

FindControl is not recursive and can only find immediate children of the control it was called on. Here you are calling it of the page instance, so it only seeks through immediate children of the page in the control tree (presumably this is only a form element).

What you need to do is to pick a server-side control right above your textboxes/buttons and run FindControl of it. For instance, let's say it is your table, which is declared as:

<table>
<%--...all the content from the post goes here...--%>
</table>

Make this table server-side:

<table id="TheTable" runat="server">

and then call FindControl on this table:

TextBox txt = TheTable.FindControl("txt" + editField) as TextBox;

You can of course keep the table client-side, and use some control that wraps this table. Just make sure that in between your control and the textbox in question there are no other server-side controls.

Andrei
  • 55,890
  • 9
  • 87
  • 108
  • Sorry I never mentioned, I tried this first then resorted to THIS as a way of checking. Using this method poses the same results – nickson104 May 14 '15 at 12:57
  • @nickson104, that's really strange. Can you please post the markup of the whole table? You can still leave just one row, I am more interested in the table declaration – Andrei May 14 '15 at 13:00
  • I agree, very interesting :-) – Paolo Costa May 14 '15 at 13:03
  • Table has been added. I cant quite put my finger on the issue – nickson104 May 14 '15 at 13:04
  • Can you try to remove the runat = server from the table and always call this.FindControl? I don't see the use for it – Paolo Costa May 14 '15 at 13:05
  • removing runat server had a large knock-on effect to many functions, however I commented them out and found no change to the initial problem, still an empty textbox is cast – nickson104 May 14 '15 at 13:09
  • @nickson104, just a sanity check - did you make sure resulting id here `"txt" + editField` is really what you expect it to be? – Andrei May 14 '15 at 13:30
0
 <table style="width:100%; margin-left:auto; margin-right:auto;" id="tblTst" runat="server">
        <tr>
            <td>
                <h2>
                    Vehicle Information
                    <asp:Label ID="lblTest" Text="THis is a Test" ForeColor="Salmon" runat="server" />
                    <asp:Button ID="btnTest" CommandArgument="0" OnClick="btnTest_click" runat="server" Text="Test" />
                </h2>
            </td>
        </tr>
        <tr>
            <td>
                    <asp:Label ID="lblTst2" Text="This is also a Test" ForeColor="Salmon" runat="server" />
                    <asp:Button ID="btnTest2" CommandArgument="1" OnClick="btnTest_click" runat="server" Text="Test" />

            </td>
        </tr>
        <tr>
            <td>
                <asp:Label ID="lblMsg" runat="server" />
            </td>
        </tr>
    </table>


    protected void btnTest_click(object sender, EventArgs e)
{
    Button btn = sender as Button;
    string comment = "";
    string editField = "";
    if (btn != null)
    {
        editField = btn.ID.Replace("btn", "");
        btn.Visible = false;
        //Getting and storing rowindex
        foreach(HtmlTableCell cl in tblTst.Rows[Convert.ToInt32(btn.CommandArgument)].Cells)
        {
            foreach (Control ctrl in cl.Controls)
            {
                if(ctrl is Label)
                {
                    Label txt = new Label();
                    txt = ctrl as Label;
                    txt.BackColor = System.Drawing.ColorTranslator.FromHtml("#FFFFB2");
                    txt.Focus();
                    comment = txt.Text;
                    lblMsg.Text = comment;
                    return;
                }
            }
        }
        //Further methods unnecessary for this question
    }
}

}

This is what I came up with, this does work; however it is a fairly dirty way to do this, I'm sure you can clean it up quite a bit. This is only intended as a starting point. The big different is that you need to look in the cell for the control not in the table or page, also the cell is an htmltable cell not just a table cell.

MaCron
  • 111
  • 6