Accessing data from dynamic control in gridview - asp.net

On Grid_RowDataBound I have added a table in the 8th cell of the current row. This table is like:
<table rules="all" border="0" style="width:100%;">
<tbody>
<tr>
<td align="center"><input name="studentgrd$ctl03$ID2VAL4" type="text" value="6" maxlength="2" id="studentgrd_ctl03_ID2VAL4" style="width:20px;"></td>
</tr>
</tbody>
</table>
On save button click, I tried to get the data using:
TextBox tb = (TextBox)studentgrd.FindControl("ID2VAL4");
TextBox tb = (TextBox)studentgrd.Rows[i].Cells[8].FindControl("ID2VAL4");//When looping through all rows
But the textboxes were null. So are the dynamic controls lost on postback? If yes, then how to retain it? If it is not, where am I going wrong?

You can assign a GridviewRow like this in your button click method:
GridViewRow gridViewRow = (GridViewRow)(((Control)sender).NamingContainer);
When assigning value you should change it to:
TextBox tb = ((TextBox)gridViewRow .FindControl("ID2VAL4"));
where gridViewRow is a GridViewRow that is used not the GridView itself.

I solved my problem: if it is a dynamically-generated control, and bounded to data source that is loaded for the first time, then on post back you have to again generate the same control and bind it, and then try to access them.
Even if the dynamic control is created and bound to a datasource just no,w it will have the changed value given by user (which surprises me, I think because of the view state of the dynamic control. Correct me if am wrong).

Related

How to get code behind variable value into repeater

I have a variable in my code behind file in asp.net say string myVariable = "SomeValue";
I use this declaration in the code-behind:
Public myVariable As String = "SomeValue"
I want to bind this string inside the in Repeater.
<td id="Td5" class="Text" style="text-align:right; width:70px;" >
<%#DataBinder.Eval(Container, "'<%=myVariable%>'", "{0:N2}")%>
</td>
The Repeater is binded using a datatable. I use vb.net
thanks for yours comments.
Set your value within session and then bind sessionh with <%=Session("yourfiledName")%>

Displaying HTML on client side after dynamically building it server side in asp.net

I am dynamically building html on the code behind (while reading data from the database and creating button controls)
So my code behind is something like:
strHTML = <table cellspacing='0' cellpadding='0' border='3'><tr><td align='center' valign='middle' width="150" height="50" class="bItem"><asp:Button CssClass='btnDashboard' width='170' Height='70' ID='Button2' runat='server' Text="MyProfile" /></td></tr></table>"
The above string is supposed to display dynamically created buttons on clientside.
My clientside code is:
<table cellspacing="0" cellpadding="3" border="0">
<tr>
<td><% %>
</td>
</tr>
</table>
How can I display the dynamically created HTML within the server tags?
I tried using div tags, but the buttons came out with no text, and I could not "click" them.
you can add html controls,tags etc by this way
create a div in your page:
<div id="divtest" runat="server"></div>
Since runat="server" is there you can access the div in your code behind.Add your html code in this way.
strHTML = "<table cellspacing='0' cellpadding='0' border='3'><tr><td align='center' valign='middle' width=""150"" height=""50"" class=""bItem""><asp:Button CssClass='btnDashboard' width='170' Height='70' ID='Button2' runat='server' Text=""MyProfile"" /></td></tr></table>"
divtest.InnerHtml = strHTML
But you cant add asp controls like that.
Button b = new Button();
b.Text = name;
b.ID = id;
b.Click += new EventHandler(Button_Click);
form1.Controls.Add(GetButton("Button1", "Click"));
You could use a PlaceHolder Class as the container for your dynamically generated buttons.
From your example, I am not sure if you are also generating a table as well, but if so, you could create it using the HtmlTable Class to generate the table containing your buttons. The table can then be added to the placeholder.
The sample code on the PlaceHolder Class page shows how to add controls to a placeholder control, buttons coincidentally.
You cannot add web server controls that way; you need to add them to the Page's control tree dynamically, if the controls are created dynamically. MSDN explains this here

In ASCX-control not doing IF/ELSE condition

There ASCX-controls that the program-loaded onto the page.
In a Repeater control in which, depending on the conditions displayed a different set of COLUMNS and DataTable with a different set of columns.
So, on the ASPX-page, this construction work Good.
<ItemTemplate>
<tr class="objectrow" href="<%# GetCompleteViewObjectLink(Convert.ToInt32(Eval("ID_Object")))%>">
<td align="center" class="c1">
<%# Eval("ID_Object") %>
</td>
<% if (GetObjectTypeName() == "Sot")
{ %>
<td align="center" class="c6">
<%# Eval("SOTName") != DBNull.Value ? Eval("SOTName") : ""%>
</td>
<% } %>
............................
But in program-loaded to page ASCX-control I have an Exception:
Error: DataBinding:
'System.Data.DataRowView' does not
contain a property named SOTName.
and another does not conform: in aspx-page my breakpoint on row
<% if (GetObjectTypeName() == "Sot")
was work off. But in ascx-control NOT.
Please, help! Why behaviour is so different? How to be?
Check your data for actual rows, i.e. row count? I would bet your DataSource is null.
I don't think you're getting data when you think you should be.
The Page Load event of the user control will execute before the aspx Page Load. If you are getting some type of parameter for your query in the .ascx in the Page Load of the .aspx, you ought to grab that in the Page_Init of the .aspx.
As TheGeekYouNeed points out, it's crucial to know when the DataSource of the Repeater is defined, as the control's events are processed before the page events.
You can add code like
<td>GetObjectTypeName='<%# GetObjectTypeName() %>'</td>
to find out whether the if() condition applies for your data.

Creating dynamic DataList controls with ID's based on bound data

As a workaround for the fact that asp:Checkboxes don't have values, I am attempting to dynamically create the ID's of checkboxes in a DataList so that it inserts the primary keys into the control ID. This is surprisingly difficult.
I have placed a PlaceHolder in my DataList ItemTemplate, then in the ItemCreated I create the checkboxes using string.Format("Checkbox{0}", DataBinder(e.Item.DataItem, "ID")). The problem is that this only works in a non-postback condition, as on postback the DataItem is null. And of course ItemDataBound isn't called on PostBack so that won't work either.
I can't seem to find a good way to handle this short of if (IsPostback) dataList.Bind(), which i don't think is a good way to do it.
Can anyone provide me with any alternatives here?
EDIT:
Some additional information. I just realized that part of the problem was because I actually have a DataList within a DataList. The reason DataItem is null is because there is no databinding on postback, and the child data is not saved to viewstate.
Basically, what i'm doing is This, although it's using a DataList rather than Repeater. So, on postback, the Children collection doesn't get set because ItemDataBound isn't called on postback.
EDIT2: To clarify, the problem is largely because of the nested datalists. I have to set the datasource of the nested datalist to a collection field of the first datalist's individual rows fields. On postback, there is no databinding, so it doesn't work.
You could use a similar technique to the one I wrote up in this answer - add a regular CheckBox, and a HiddenField control in the ItemTemplate, and bind the HiddenField to the primary key value e.g.
<ItemTemplate>
<tr>
<td>
<asp:CheckBox runat="server" ID="MyCheckBox" AutoPostBack="true" oncheckedchanged="MyCheckBox_CheckedChanged" />
<asp:HiddenField runat="server" id="DatabaseKeyHiddenField" Value='<%# Eval("DatabaseKey") %>' />
</td>
</tr>
</ItemTemplate>
protected void MyCheckBox_CheckedChanged(object sender, EventArgs e)
{
CheckBox selectedCheckBox;
DataListItem selectedDataListItem;
HiddenField databaseKeyHiddenField;
string databaseKey;
// Cast the sender object to a CheckBox
selectedCheckBox = (CheckBox)sender;
// Walk up the tree one level so we get the container for both controls
selectedDataListItem = (DataListItem)selectedCheckBox.Parent;
// Get the HiddenField control ...
databaseKeyHiddenField = (HiddenField)selectedDataListItem.FindControl("DatabaseKeyHiddenField");
// ... and read the value
databaseKey = databaseKeyHiddenField.Value;
// Go off and do a database update based on the key we now have
...
}
It's a bit of a workaround rather than exactly what you want to do, but it works!

jQuery help - find span in current table cell and adjacent cell

I have an HTML table on my form. Column 1 contains a dropdown and a hidden span, Column 2 contains a hidden span. I need to show both spans and hide the drop down after a user makes a selection. I have done something similiar in other apps using code like this
var ddl_change = function() {
var ddl = this;
$("lbl1").text(ddl.options[ddl.selectedIndex].text).show();
$(ddl).hide();
}
if have 4 dropdowns (rows in the table). For code reuse I would like to use the same handler. I suppose I could write 4 seperate handlers, but that seems like a waste.
The html for a row looks like this
<tr>
<td>
<asp:DropDownList runat="server" ID="ddlbc1" />
<asp:Label runat="server" ID="lbl1" />
</td>
<td>
<asp:Label runat="server" ID="bd1" />
</td>
</tr>
I have the full client controls Id's if I need them. Anyways, is there a way within this single function to handle any row? I added client change event handlers to all the necessary drop downs and pointed them to this single function. I verified they are all correctly wired up. I want lbl1 textx to be the ddl selectedValue, and bd1, in the adjacent cell, to have ddl selectedText. Any help from the jQuery guru's would be appreciated. Thanks guys!
Cheers,
~ck in San Diego
$("td select").change(function(e){
$(this).hide().parent().parent().find("span").show();
});
Give it a whirl. You could also manage it by directly modifying the CSS, or changing the class.
You could target the entire table at once rather than a row using $("#table-id-name select") instead of the $("td select") (which will select all TD's in the entire page).
If you gave your lists/spans classes that would help to identify them, but it could be done otherwise.
$('table select').change( function() {
var $this = $(this);
$this.hide();
var lbl = $this.next('span');
var bd = $this.closest('td').next('td').find('span');
lbl.text( $this.val() ).show();
bd.text( $this.find('option:selected').text() ).show();
});

Resources