Why is my ASP.NET Button control not calling the appointed function? - asp.net

I want to set up a search functionality on my web site. The user types some information into a text box and click a search button. Upon clicking the search button, a database is searched using the text in the text box, and the results are displayed in a table. If the text in the text box matches one result from the database perfectly, rather than displaying a list of results the page is populated with detailed information about the matching result.
In order to make it easier to match a result exactly, I want to add a button next to each result which "selects" that result, filling the text box with that result's text and therefore populating the page with the details. Here's what I have.
Upon clicking the search button, after the check to see if a result is matched exactly, I create a table which contains the results and the buttons:
for(int x=0; x < res_list.Length; x++)
{
TableRow newRow = new TableRow();
TableCell textCell = new TableCell();
TableCell buttonCell = new TableCell();
buttonCell.ID = "bc" + x;
Button cellButton = new Button();
cellButton.ID = "btn" + x;
textCell.Text = res_list[x];
textCell.Attributes.Add("Width","60%");
cellButton.Text = x.ToString();
// cellButton.OnClientClick = "NameClick"; This property refers to client-side scripts, which I am not using.
cellButton.Click += new EventHandler(NameClick);
buttonCell.Controls.Add(cellButton);
newRow.Cells.Add(firstCell);
newRow.Cells.Add(buttonCell);
myTable.Rows.Add(newRow);
}
I have tried both the OnClientClick method and the Click method seen above, both of which have yielded the same results.
My NameClick function is as follows:
void NameClick(object sender, EventArgs e)
{
Button sendButton = (Button)sender;
int index = Int32.Parse(sendButton.Text);
SearchTextBox.Text = myTable.Rows[index].Cells[0].Text;
return;
}
I set up a breakpoint at the beginning of the NameClick function, and when I click one of these buttons it is never reached. Why is this function not being called by my buttons?
EDIT: I want to accomplish this without using JavaScript, if possible.

You use cellButton.OnClientClick = "NameClick";, but do you actually have a NameClick function in your javascript? If not, clicking the button will cause a JS error which will probably block the postback.
Other than that, it is advisable to assign explicit ID's to controls which you create programatically. Otherwise the autogenerated ID's may change on postback, which will prevent control events from firing.
Something like the following should work (not tested):
myTable.ID = "someid";
for (int x=0; x < res_list.Length; x++)
{
TableRow newRow = new TableRow();
newRow.ID = "r" + x;
TableCell textCell = new TableCell();
TableCell buttonCell = new TableCell();
buttonCell.ID = "bc" + x;
Button cellButton = new Button();
cellButton.ID = "btn" + x;
textCell.Text = res_list[x];
textCell.Attributes.Add("Width","60%");
cellButton.Text = x.ToString();
//cellButton.OnClientClick = "NameClick"; // not needed unless you have actual JS for it
cellButton.Click += new EventHandler(NameClick);
buttonCell.Controls.Add(cellButton);
newRow.Cells.Add(firstCell);
newRow.Cells.Add(buttonCell);
myTable.Rows.Add(newRow);
}

cellButton.OnClientClick should point to a client-side function, i.e. JavaScript. Do you have a JS function somewhere?
If the answer is no, then we've found your problem. You should create one. It will be helpful to set your ClientIDMode property of your dynamically generated controls to Static or Predictable, so your JS function can easiliy access them.
Do you need assistance with the JS function?

when you click on the button, the page start the life cycle again and your control Does not exist in the page you need to create the control again or save it in the viewstate or use control state
when he call back in the life cycle
in the page life cycle event SaveControlState, loadControlState
if you want to create a javascript click event you need to make sure that the control doesnt call to server side event for this in the javascript function you need to return false

you have to add this event in your asp syntax for button.
<asp:Button runat="server " OnClick="ButtonClick"/>

Related

How can I clear a datatable in asp listview?

When I use the code below, I remove the datatable values, but the data table structure still exists and displays empty fields (see pics) with the DOM explorer showing an empty table and table rows.
How can I clear the datatable values and the table itself? This way when I repopulate search again, the empty smaller table isn't present?
lvwOutput.Items.Clear();
lvwOutput.DataSource = null;
lvwOutput.DataBind();
Before
After items.clear and datasource = null
This is ridiculous and I believe there is a better way to do this, but the never ending server/client battle makes this harder than it should be. My listview binded to a datatable is called lvwOutput.
In my btnClear I had to put the following. You cannot hide the element or clear the items in the server side asp code for this to work
ScriptManager.RegisterStartupScript(Page, GetType(), "emptyTable", "javascript:emptyTableRows(); ", true);
In my javascript code I had to put the following, this clears the client code
function emptyTableRows(){
var tableHeaderRowCount = 0;
var table = document.getElementById('lvwOutputTable');
var rowCount = table.rows.length;
for (var i = tableHeaderRowCount; i < rowCount; i++) {
table.deleteRow(tableHeaderRowCount);
}
}
And then in the portion of my code that would display the listview and datatable when the user initiates another sql search. This clears the server side.
lvwOutput.Items.Clear();
lvwOutput.DataSource = null;
lvwOutput.DataBind();
You can create a property the stores the data table in session that way you can access it during the click event.
DataTable dtbleDataSource
{
get
{
return Session["dataSource"] as DataTable
}
set
{
Session["dataSource"] = value;
}
}
In your click event you can say:
dtbleDataSource.Reset();

Dynamic controls(Textbox) in asp.net

I want to create dynamic text boxes during run time.
Suppose im gettng a text from a database as "# is the capital of India" now i want to replace that "#" by text box while it is rendered to user as below
<asp:TextBox runat="server" id = "someid"></asp:TextBox> is the capital of India
Im able to get the textbox and text as combination. However I cannot access the textboxes with the given id and when any event occurs on the page the textboxes are lost as they logically does not exist untill their state is stored.
I also went through the concepts of place holder and Viewstate to store the dynamically created controls and make their id's available for the methods, but as far as I tried I could not meet the textbox and text combination requirement.
Im looping over the entire text recieved from database and checking if there is any"#". Is yes then i want to replace it with a textbox on which i can call methods to take back the value entered in the text box to database and store it.
eg: text is "#" is the capital of India
for (int i = 0; i < que.Length; j++) //que holds the text
{
if (que[i] == '#')
{
//Textbox should be created
}
else
{
//the texts should be appended before or after the textbox/textboxes as text demands
}
}
On button click I'm passing request to database, which will send me necessary details i.e. question text, options and also saves the current checked value etc.
protected void BtnLast_Click(object sender, EventArgs e)
{
CheckBox1.Checked = false;
CheckBox2.Checked = false;
CheckBox3.Checked = false;
CheckBox4.Checked = false;
QuestionSet q = new QuestionSet();
StudentB b = new StudentB();
q = b.GetQuestion(1, 1, qid, 'L', 0, Checked, date);
qid = Convert.ToInt32(q.Question_Id);
Checked = q.Checked;
if (q.Question_Type == 11) //indicates its objective Question
{
//ill bind data to checkboxes
}
else if (q.Question_Type == 12) // indicate its fill in the blanks question
{
for (int j = 0; j < que.Length; j++)
{
if (que[j] == '#')
{
count++;
string res = "<input type = 'text' runat = 'server' id ='TxtBoxFillUp" + count + "'/>";
htm = htm.Append(res);
}
else
{
htm = htm.Append(que[j]);
}
}
}
}
Any help will be greatly appreciated, thanks in advance.
Adding control in the way you do it won't create control as asp.net creates it. You do have to create controls as usual .net object.
TextBox myNewTextBox = new TextBox() {};
// Set all initial values to it
And add this cotrol to placeholder or panel, whatever you use. Keep in mind that asp.net page events fire even if you use update panel, so in order to maintain state and events of newly created controls you have take care of creating such controls long before page's Load event fires. Here is my answer to another simialiar question.
Seeing the requirements you have:
1.) You need to use JavaScript. Since the ASP.NET will not recreate controls which are dynamically added. Dynamically added controls need to be recreated after every postback. This is the reason why your TextBoxes are Lost after every postback.
2.) You can write JavaScript code to Hide and show the textboxes for blank texts since at every button click you can call Client side functions using: OnClientClick() property of buttons.
3.) Also to Get the TextBoxes using ID property, add them in Markup( .aspx ) portion itself.

ASP.NET control lifecycle. Control property changes only available on next load

I have built a pager control with various properties, for example Start to indicate the first record which should be rendered. This is embedded in another control which actually renders the list of records. The properties' getters and setters use ViewState to persist and retrieve the values.
The links in the pager are dynamically created during the page_load. On each link, the anchor.ServerClick delegate is wired up to a lambda that sets the Start property on the pager control.
When I debug the page, I can see that the Start property is indeed updated, but that the changed value is only available the next time I load the page, presumably persisted via the ViewState mechanism.
What this means in practice is that the embedding control doesn't see the updated values of these properties in time to render the correct list. How can I have the visitor's click update the pager properties before they get used rather than afterwards?
EDIT: adding some code
Called from the Page_Load of the main control, I have a loop that references the properties of the pager. This loop determines the items which will be displayed, and if the control properties were updated by this point, it would display the correct records, but that's not the case.
for (int i = pager.Start - 1 ;
i < queryResults.Count() && i <= (pager.Start + pager.PageSize); i++) {
In the pager control, also called from the Page_Load, there's code like this, that adds child controls and wires up the delegate.
HtmlAnchor a = new HtmlAnchor();
a.HRef = "#";
a.InnerText = page.ToString();
newStartNumber = ((page - 1) * this.PageSize) + 1;
a.Attributes["data-start"] = newStartNumber.ToString();
a.ServerClick += (sender, e) =>
{ this.Start = int.Parse(((HtmlAnchor)sender).Attributes["data-start"]); };
li.Controls.Add(a);
ul.Controls.Add(li);
So when these anchors are clicked, the pager's Start property is updated, but it's too late.
As far as I know, these code parts seem ok, provided :
Your Page property looks like this :
public int Page
{
get { return ViewState["Page"] == null ? 0: (int)ViewState["Page"]; }
set { ViewState["Page"] = value; }
}
and this :
for (int i = pager.Start - 1 ;
i < queryResults.Count() && i <= (pager.Start + pager.PageSize); i++) {
is in the preRender of your parent control.
And this :
HtmlAnchor a = new HtmlAnchor();
a.HRef = "#";
a.InnerText = page.ToString();
newStartNumber = ((page - 1) * this.PageSize) + 1;
a.ServerClick += (sender, e) => { this.Start = newStartNumber; };
li.Controls.Add(a);
ul.Controls.Add(li);
is in the pageload (or init) of your pager control. (maybe you don't need the data-start attribute)
You should give Ids to your HtmlAnchors.

Find ListBoxes in ASP .NET

i have created dynamic listboxes (4 to 10) in ASP.NET.
and my question is , How do i find the dynamically created listboxes using c#?
thanks
Sure... and i appreciate your help . below code i am using for creating dynamic LB
protected void btndyfilter_Click(object sender, EventArgs e)
{
int numberOfListBox = lbFilter.GetSelectedIndices().Length;
string lbname = lbFilter.SelectedValue;
for (int i = 0; i < numberOfListBox; i++)
{
ListBox listb = new ListBox();
ListItem lItem = new ListItem();
listb.SelectionMode = System.Web.UI.WebControls.ListSelectionMode.Multiple;
listb.Height = 150;
listb.Width = 200;
lItem.Value = i.ToString();
lItem.Text = lbname;
listb.Items.Add(lItem);
panFilter.Controls.Add(listb);
//once we created the LB dynamically i need to populate each LB with the corresponding values
connstr2 = System.Configuration.ConfigurationManager.ConnectionStrings["connstr"].ConnectionString;
conn2.ConnectionString = connstr2;
conn2.Open();
CubeCollection CubeList = conn2.Cubes;
string cb = ddlCubeList.SelectedItem.Text;
//need to remove the Hardcoded Code
foreach (Member dimem in CubeList[cb].Dimensions["Date"].Hierarchies["Calendar Date"].Levels["Date"].GetMembers())
{
ListItem Memlist = new ListItem();
Memlist.Text = dimem.UniqueName;
lbFilter.Items.Add(Memlist);
}
}
panFilter.Visible = true;
panCubeDef.Visible = true;
}
so this will create the LB i believe :)... and Inside the commented code i need to use to populate for each LB item ..perhaps it bit hardcoded which i need to remove. so i all dynamic LBs are populated then the selected items from all LBs will come into the where clause in my MDX query..hope i did not confuse you
There is 2 way either you can store dynamic control detail with dictionary or just find when you want to use it using some code like this
Control GetControlByName(string Name)
{
foreach(Control c in this.Controls)
if(c.Name == Name)
return c;
return null;
}
while generating ListBox dynamically, give ListBox ID as:
lstBoxNo1, lstBoxNo2. lstBoxNo3 etc. where 1,2,3(no) will be from count.
like
int count=1;
generate listbox control
listboxid=lastBoxNo+count;
count++
`by doing this, u have control over id's.
else use
http://stackoverflow.com/questions/3731007/using-findcontrol-to-find-control
using this link to understand findcontrol.
The points that you wont to find that dynamic controls are.
The moment you first render the page.
On every other post back.
In the case of 1, then you better keep a variable on your page that keep that creations.
In the case of 2, when you have post back, you need to store somehow the creations of your control in the page when you render it. One good place is to keep that information on the viewstate.
You can also on the post back, just to check if you have any post back valued from controls that you have named with a serial numbering starting from 1, eg You start looking if you have post back from ControlName_1, then ControlName_2, and when you not found any other value you end.

ListView -Dynamic Controls and DataPager events

I have a listView control which is bound to an object datasource. In the ListView1_ItemDataBound event, I am generating some dynamic controls. I do this because depending on a particular column value, i might need to generate textbox, radio button, check box etc.
Some code here:
ListViewDataItem item = (ListViewDataItem)e.Item;
typez = Convert.ToInt32(DataBinder.Eval(item.DataItem,"Type").ToString());
if (typez == 1) //1 means generate radibutton
{
string[] options = DataBinder.Eval(item.DataItem, "QuestionDetail").ToString().Split(new string[] { delimiter }, StringSplitOptions.None);
questionID = Convert.ToInt32(DataBinder.Eval(item.DataItem, "Question_ID").ToString());
int optionCount = 1;
RadioButtonList rbl = new RadioButtonList();
//set ID for the radiobtnList to the questionid no.
rbl.ID = "mcq_" + questionID;
foreach (string s in options)
{
//adds the MCQ options to list item
ListItem li = new ListItem(Util.GetAlphabet(optionCount).ToUpper() + ". " + s, Util.GetAlphabet(optionCount).ToUpper(), true);
rbl.Items.Add(li);
optionCount++;
}
//PlaceHolder PlaceHolder1 = (PlaceHolder)e.Item.FindControl("PlaceHolder1");
PlaceHolder1.Controls.Add(rbl);
I have DataPager also. When I go to the next page I want to somehow capture the user response in the previous page. Otherwise, all the user response is lost. I tried using ListView1_PagePropertiesChanging event. But here I somehow do not seem to get the dynamic controls in the page.
I need to get the radio button selected value so that I can save it or put in some session variable so that when user comes back to this page he can see his previuos values.
Could someone please suggest some insight on what I am doing wrong.
Problem is that you have to create controls in OnInit, then ViewState persister can do it's job. If you do it after OnInit, in ItemDataBound, when Postback is triggered, controls doesn't exists and their's viewstate isn't deserialized.
To access values of radio buttons and get selected one, you have to look at Request.Form dictionary and find it.

Resources