dynamic dropdownlist in asp.net - c#

I created dropdownlist at runtime when a button is clicked.and i palced another button to get the selected text from dynamic dropdownlist.When i try to retrieve the selected text from dropdownlist it gives me the error called object reference not set, following is my code.
TableRow tr;
TableCell tc;
DropDownList dp;
TextBox txt;
protected void Button1_Click(object sender, EventArgs e)
{
int no = int.Parse(TextBox1.Text);
for (int i = 0; i < no; i++)
{
tr = new TableRow();
tr.BorderStyle = BorderStyle.Groove;
for (int j = 0; j < 1; j++)
{
tc = new TableCell();
tc.BorderStyle = BorderStyle.Groove;
dp = new DropDownList();
//form1.Controls.Add(dp);
txt = new TextBox();
dp.Items.Add("hello");
tc.Controls.Add(dp);
tc.Controls.Add(txt);
tr.Cells.Add(tc);
}
Table1.Rows.Add(tr);
}
}
protected void Button2_Click(object sender, EventArgs e)
{
TextBox1.Text =((DropDownList)this.FindControl("dp")).SelectedItem.Text;
}

You can't do it this way. Remember that on every request, you get a new page object, and new copies of all the controls in it. Any control you add dynamically must be added the same way every single time, otherwise it won't exist.
In this case, you add it once, when the button is clicked. When you click button2, a request is generated and a new page object is created that no longer has your dropdownlist, because it is only ever added in the button1 handler.
The easiest thing to do would be add your dropdownlist to the page normally but just set Visible to false. Then when they click button 1, set Visible to true. This will ensure that your dropdownlist will always be present.
Dynamic controls are tricky, and should be avoided when possible, especially if you're new to ASP.Net.

Actually, I was able to make it work..
I created a dataset ahead of the table creation, then:
tc = new TableCell();
dd= new DropDownList();
ddl.ID = dd1;
foreach (DataRow dr in dst.Tables[0].Rows)
{
ddl.Items.Add(new ListItem(dr["Text"].ToString(),dr["Value"].ToString()));
}
tcActions.Controls.Add(ddlActions);
I'm not an expert or anything, I just peck at it until I make it do what I want.

Related

My generated ASP.NET Button doesn't actually do anything

Right now I've got a method that's dynamically generating a table of information based on input in a search bar, with a button located on each row. When pressed, that button is supposed to take the information present in its row and process it.
My problem is that my buttons aren't doing anything, but I'm not exactly sure how to fix it. Even trying to post to the output panel in VS doesn't work. As soon as I press one, all it does is wipe out all of my values - everything in my table - all back to default by refreshing the page.
// The bottom section of the method which 'generates' buttons for each row made in the for loop - everything works perfect to this point
TableCell addButtonCell = new TableCell();
Button addButton = new Button();
addButton.Text = "Add";
addButton.Width = 75;
addButton.Click += new EventHandler(addButton_Click);
addButtonCell.Controls.Add(addButton);
row.Cells.Add(addButtonCell);
tblResults.Rows.Add(row);
}
// button event handler
public void addButton_Click(object sender, EventArgs e) {
System.Diagnostics.Debug.Write("TESTING!!!!!"); // Tried this, no effect
}
Whatever controls are created Dynamically, needs to be created each time the page loaded.
SOLUTION:
You need to do the way I done in the following...
TableRow row;
TableCell cell;
protected void Page_Load(object sender, EventArgs e)
{
if (this.IsPostBack)
{
this.ReloadDynamicControls();
}
else
{
DynamicControls = new List<Button>();
}
}
private void ReloadDynamicControls()
{
if (this.DynamicControls != null)
{
foreach (Button button in DynamicControls)
{
button.Click += new EventHandler(btnKill_Click);
row = new TableRow();
cell = new TableCell();
cell.Controls.Add(button);
row.Controls.Add(cell);
Panel1.Controls.Add(row);
}
}
}
private List<Button> DynamicControls
{
get { return Session["DynamicControls"] != null ? (List<Button>)Session["DynamicControls"] : null; }
set { Session["DynamicControls"] = value; }
}
And you need change you generate button method with this code:
TableRow tr = new TableRow();
tblResults.Controls.Add(tr);
Button addButton = new Button();
addButtonCell = new TableCell();
addButtonCell.Controls.Add(addButton);
tr.Controls.Add(addButtonCell);
addButton.Width = 75;
addButton.Text = "Add";
addButton.ID = "btn_" + this.DynamicControls.Count.ToString();
addButton.Click += new EventHandler(addButton_Click);
addButton.EnableViewState = true;
DynamicControls.Add(addButton);
tr.TableSection = TableRowSection.TableBody;
tblResults.Rows.Add(tr);
The original solution here
You'd wanna include here that the query should have a WHERE clause and should be limitted by 1, ensuring that actually one result is returned. then the if should also be changed to if($result->num_rows == 0).

Get Value Dynamic Textbox in C#

I made dynamic textboxes and keep it List
private void ConvertButton_Click(object sender, EventArgs e)
{
List<TextBox> textBoxes = new List<TextBox>();
foreach (Control item in this.Controls)
{
if (item is TextBox)
{
TextBox txt = item as TextBox;
textBoxes.Add(txt);
}
}
}
I get all of textboxes value but i have a problem. For examples; if user add 3 label like (A,B,C) and add Textboxes for them like (labelA has 2,labelB has 3,labelC has 1) and textboxes get value like array (textboxes[0] has value).The problem is i dont know which label has which value.
I added Textbox just like this:
private void addNewTextbox(object sender, EventArgs e)
{
Button button = (Button)sender;
List<TextBox> textBoxes = button.Tag as List<TextBox>;
if (textBoxes == null)
button.Tag = textBoxes = new List<TextBox>();
TextBox textBox = new TextBox();
textBoxes.Add(textBox);
textBox.Location = new Point(90 * textBoxes.Count, button.Top);
textBox.Size = new Size(50, 50);
this.Controls.Add(textBox);
}
I try to show screen for example;
LabelA-->Textbox1 , Textbox2
</br>
labelB -->Textbox3
</br>
LabelC --> Textbox4 , Textbox5 , TextBox6
Every control that is added has a Name property. Use this property to link the different controls together. For example (and you should come up with your own naming convention), you could do this:
LabelA --> TextboxA1, TextboxA2
LabelB --> TextboxB1
LabelC --> TextboxC1, TextboxC2, TextboxC3
If you wish to have a more complete (i.e. complex) solution, you could:
Create your own control that inherits from TextBox
Add a property for the name of the associated Label control
Set this property when a new control is instantiated
Label[] labelArray = new Label[10];
for (int i = 0; i < labelNumber; i++)
{
labelArray[i] = new Label();
labelArray[i].Text = states[i] + "-->";
this.Controls.Add(labelArray[i]);
labelArray[i].Top = 100 + i * 30;
labelArray[i].Left = 10;
labelArray[i].Width = 30;
}
i did label-created just like this.labelnumber is how many label user wants.#interceptwind
I am trying very hard to understand your question, I guess you are trying to link the user-created textboxes to specific labels? Forgive me if I am completely wrong. How about structure your code to something like this:
Note: Edited with OP's new code
Dictionary<Int, List<TextBox>> label_Textboxes_Dict = new Dictionary<Int, List<TextBox>>();
List<Label> labelArray = new List<Label>(); //I suggest use list as you don't know the array size beforehand
void addLabel(int labelNumber)
{
int currentLabelArrayCount = labelArray.count; //So that users can add multiple times
for (int i = currentLabelArrayCount; i < currentLabelArrayCount +labelNumber; i++)
{
labelArray.Add(new Label());
labelArray[i].Text = states[i] + "-->";
this.Controls.Add(labelArray[i]);
labelArray[i].Top = 100 + i * 30;
labelArray[i].Left = 10;
labelArray[i].Width = 30;
label_Textboxes_Dict.Add(i, new List<TextBox>());
}
}
void addTextBoxForLabel(int labelNum)
{
TextBox t1 = new TextBox();
TextBox t2 = new TextBox();
//etc...
if (label_Textboxes_Dict.ContainsKey(labelNum))
{
label_Textboxes_Dict[labelNum].Add(t1);
label_Textboxes_Dict[labelNum].Add(t2);
}
}
void doSomethingForAllTextboxesOfLabel(int labelNum)
{
List<TextBox> listOfTextBoxes;
if(label_Textboxes_Dict.TryGetValue(labelNum, out listOfTextBoxes))
{
foreach(TextBox tb in listOfTextBoxes)
{
//do your stuff
}
}
}

Unable to SetFocus on a dynamically created text box

I am generating the text boxes dynamically.Table rows are created dynamically too, and these text boxes are added to those dynamically created row cells and they are added to the table using the following code
protected override void OnInit(EventArgs e)
{
PopulateTextBoxes();
SetFocus();
base.OnInit(e);
}
protected void PopulateTextBoxes()
{
int quantityRequired = 0;
quantityRequired =GetQuantity();
for (int j = 0; j < quantityRequired; j++)
{
TableRow row = new TableRow();
TableCell cell1 = new TableCell();
TextBox tb = new TextBox();
tb.ID = j.ToString() +"_RowTbx"
tb.AutoPostBack = true;
tb.TextChanged += new EventHandler(tb_TextChanged);
cell1.Controls.Add(tb);
row.Cells.Add(cell1);
TableCell cell2 = new TableCell();
CheckBox chBox = new CheckBox();
chBox.CheckedChanged += new EventHandler(chBox_CheckedChanged);
chBox.AutoPostBack = true;
cell2.Controls.Add(chBox);
row.Cells.Add(cell2);
TableCell cell3 = new TableCell();
Image img = new Image();
img.Width = Unit.Pixel(25);
img.Height = Unit.Pixel(25);
img.ImageUrl = "HttpRuntime.AppDomainAppVirtualPath" + "/Images/" +"img.jpeg";
cell3.Controls.Add(img);
row.Cells.Add(cell3);
tbl_Serial.Rows.Add(row);
}
LoadDataIfExists();
}
private void tb_TextChanged(object sender, EventArgs e)
{
//I have implemented code to validate the text entered in the text box.
}
protected void SetFocus()
{
int emptytbxRow = 0;
TextBox tbx = new TextBox();
for (int i = 0; i < tbl_Serial.Rows.Count; i++)
{
string tbxId = i.ToString() + "_RowTbx";
string text = ((TextBox)tbl_Serial.Rows[i].Cells[0].FindControl(tbxId))).Text;
if (text == null || text==string.Empty)
{
tbx=((TextBox)(tbl_Serial.Rows[i].Cells[0].FindControl(tbxId)));
if (tbx != null)
tbx.Focus();
}
}
protected void LoadDataIfExists()
{
List<string> lstData=Service.GetData(int someNum)
for (int j = 0; j < lstData.Count; j++)
{
string tbxID = j.ToString() + "_RowTbx";
TextBox tbx = (TextBox)tbl_Serial.Rows[j].Cells[0].FindControl(tbxID);
tbx.Text = lstData[j];
}
}
When I debug, the tbx.focus seems to hit rightly but i do not see the cursor blinking on the text box in my UI.I do not know if I am missing something imp. Thank you.
Edit: Sorry I was not clear. When the page loads, the text boxes may contain data, but not all text boxes contain data. So whenever the page loads there are a few text boxes with data and there are empty ones. I want the cursor to be at the first empty box.
Given that you know which text box is your first empty one you want to also be aware of the page life cycle. OnInit is to early in the page life cycle for this to occur as the page is still initializing and the objects haven't yet rendered to the form. Try OnLoad or use PreRender to set focus to your item right before the form is rendered.
The link below will show you all available methods that you can hook into during the cycle.
ASP Page Lifecycle
For some unknown reason , C#code with the same logic as below did not work, while javascript works. Hope the following helps someone in future. Thank you Liqua for providing the start.
window.onload = function () {
FindWhichTextBoxIsEmpty();
}
function FindWhichTextBoxIsEmpty() {
var tableSerial = document.getElementById('tbl_Serial');
for (var i = 0; i < tableSerial.rows.length-1; i++) {
var ID = i.toString() + "_RowTbx";
if (document.getElementById(ID).value!="") {
var tb = document.getElementById(ID).value;
if (tb != "") {
if (i + 1 < tableSerial.rows.length-1) {
var nextID = (i + 1).toString() + "_RowTbx";
document.getElementById(nextID).focus();
}
}
}
}
}
didn't got your question clearly, what i got is you created a textbox dynamically, and trying to focus it at runtime.. May be this work for you try creating tb += getFocus event, or try tb.Focus();

Click event for dynamically created link buttons not firing?

This is application i am doing in c# web application
I am creating link buttons dynamically as below.
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
LinkButton ln = new LinkButton();
ln.Text = ds.Tables[0].Rows[i].ItemArray[0].ToString();
ln.ID = ds.Tables[0].Rows[i].ItemArray[1].ToString();
divonlne.Controls.Add(ln);
divonlne.Controls.Add(new LiteralControl("<br/>"));
}
my click event is as follows
ln.Click += new EventHandler(Clicked);
In my click event i am getting the linkbutton text and Id as follows
protected void Clicked(object sender, EventArgs e)
{
LinkButton lno = sender as LinkButton;
Session["Toname"] = lno.Text;
Session["idto"] = lno.ID;
}
But this is firing only when the last link button is clicked.
Can anyone help me out?
You already wrote how you subscribe the Click Event, but in your sample i cant see it.
Maybe you subscribe on the wrong place. This works...
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
LinkButton ln = new LinkButton();
ln.Text = ds.Tables[0].Rows[i].ItemArray[0].ToString();
ln.ID = ds.Tables[0].Rows[i].ItemArray[1].ToString();
ln.Click += new EventHandler(Clicked);
divonlne.Controls.Add(ln);
divonlne.Controls.Add(new LiteralControl("<br/>"));
}
When using dynamic controls in a custom control, remember to decorate your class with the INamingContainer interface. This ensures recreated controls fit correctly into the hierarchy and remember which events they are supposed to handle.

how do I host a control in a DataGridViewCell for displaying as well as editing?

I've seen How to: Host Controls in Windows Forms DataGridView Cells which explains how to host a control for editing a cell in a DataGridView. But how can I host a control for displaying a cell?
I need to display a file name and a button in the same cell. Our UI designer is a graphic designer not a programmer, so I have to match the code to what he's drawn, whether it's possible - or wise - or not. We're using VS2008 and writing in C# for .NET 3.5, if that makes a difference.
UPDATE: The 'net suggests creating a custom DataGridViewCell which hosts a panel as a first step; anyone done that?
As per your "UPDATE", creating a custom DataGridViewCell is the way this is done. I've done it, and it doesn't require that much modification from the example code available from the MSDN. In my case, I needed a bunch of custom editing controls, so I ended up inheriting from DataGridViewTextBoxCell and DataGridViewColumn. I inserted into my class (the one inherited from DataGridViewTextBoxCell) a new custom control which implemented IDataGridViewEditingControl, and it all just worked.
I suppose that in your case, you could write a PanelDataGridViewCell which would contain a control MyPanelControl which would inherit from Panel and implement IDataGridViewEditingControl.
Rather than use a datagridview, how about using a TableLayoutPanel instead. Create your control that has a label and a button and events and fill your layout panel with them. Your control becomes the cell so to speak. It doesn't take much to make the table layout panel to look like a datagridview, if that is the layout style you want.
There are two ways to do this:
1). Cast a DataGridViewCell to a certain cell type that exists. For example, convert a DataGridViewTextBoxCell to DataGridViewComboBoxCell type.
2). Create a control and add it into the controls collection of DataGridView, set its location and size to fit the cell that to be host.
See Zhi-Xin Ye's sample code below which illustrates the tricks:
private void Form_Load(object sender, EventArgs e)
{
DataTable dt = new DataTable();
dt.Columns.Add("name");
for (int j = 0; j < 10; j++)
{
dt.Rows.Add("");
}
this.dataGridView1.DataSource = dt;
this.dataGridView1.Columns[0].Width = 200;
/*
* First method : Convert to an existed cell type such ComboBox cell,etc
*/
DataGridViewComboBoxCell ComboBoxCell = new DataGridViewComboBoxCell();
ComboBoxCell.Items.AddRange(new string[] { "aaa","bbb","ccc" });
this.dataGridView1[0, 0] = ComboBoxCell;
this.dataGridView1[0, 0].Value = "bbb";
DataGridViewTextBoxCell TextBoxCell = new DataGridViewTextBoxCell();
this.dataGridView1[0, 1] = TextBoxCell;
this.dataGridView1[0, 1].Value = "some text";
DataGridViewCheckBoxCell CheckBoxCell = new DataGridViewCheckBoxCell();
CheckBoxCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
this.dataGridView1[0, 2] = CheckBoxCell;
this.dataGridView1[0, 2].Value = true;
/*
* Second method : Add control to the host in the cell
*/
DateTimePicker dtp = new DateTimePicker();
dtp.Value = DateTime.Now.AddDays(-10);
//add DateTimePicker into the control collection of the DataGridView
this.dataGridView1.Controls.Add(dtp);
//set its location and size to fit the cell
dtp.Location = this.dataGridView1.GetCellDisplayRectangle(0, 3,true).Location;
dtp.Size = this.dataGridView1.GetCellDisplayRectangle(0, 3,true).Size;
}
MSDN Reference : how to host different controls in the same column in DataGridView control
Using the 1st method looks like this:
Using the 2nd method looks like this:
Additional info: Controls in the same DataGridView column dont render while initializing grid
Usually you should host controls in winfors forms datagridview cells as shown here
But if you need your control to be always visible, what you can do is make a custom column inheriting from DataGridViewImageColumn. Add the control to the datagridview. Set the DefaultCellStyle.Nullvalue of the control to a bitmap of the control you want always shown on the data gridview. Then using the cellMouseEnter event you can display and reposition the control to display over the image cell. This gives the appearance that your custom control is always visible without using as much resources as creating a new instance of your control for every row added to the datagridview. This will help performance quite a bit.
Here is what I did with my custom “AddRemove” usercontrol.
public class AddRemoveColumn : DataGridViewImageColumn
{
private AddRemove SelectionControl = null;
private Bitmap SelectionControlImage = null;
public AddRemoveColumn()
{
SelectionControl = new AddRemove();
}
#region Set Up Column
protected override void OnDataGridViewChanged()
{
base.OnDataGridViewChanged();
if (DataGridView != null)
{
Activate();
}
}
private void Activate()
{
SelectionControl.LostFocus += SelectionControl_LostFocus;
this.DataGridView.CellMouseEnter += DataGridView_CellMouseEnter;
this.DataGridView.BackgroundColorChanged += DataGridView_BackgroundColorChanged;
this.DataGridView.RowHeightChanged += DataGridView_RowHeightChanged;
SelectionControl.OnAddClicked += AddClicked;
SelectionControl.OnRemoveClicked += RemoveClicked;
this.DataGridView.Controls.Add(SelectionControl);
SelectionControl.Visible = false;
this.Width = SelectionControl.Width;
SelectionControl.BackColor = this.DataGridView.BackgroundColor;
this.DataGridView.RowTemplate.Height = SelectionControl.Height +1;
foreach (DataGridViewRow row in DataGridView.Rows)
{
row.Height = SelectionControl.Height+1;
}
SetNullImage();
}
#endregion
private void AddClicked(int RowIndex)
{
MessageBox.Show("Add clicked on index=" + RowIndex.ToString());
}
private void RemoveClicked(int RowIndex)
{
MessageBox.Show("Removed clicked on index=" + RowIndex.ToString());
}
private void SetNullImage()
{
if (SelectionControlImage != null)
{
SelectionControlImage.Dispose();
}
SelectionControlImage = new Bitmap(SelectionControl.Width, SelectionControl.Height);
SelectionControl.DrawToBitmap(SelectionControlImage, new Rectangle(0, 0, SelectionControlImage.Width, SelectionControlImage.Height));
this.DefaultCellStyle.NullValue = SelectionControlImage;
}
private void DataGridView_RowHeightChanged(object sender, DataGridViewRowEventArgs e)
{
if (e.Row.Height <= 40)
{
e.Row.Height = 40;
}
SelectionControl.Visible = false;
SetPosition(Index, e.Row.Index);
}
private void DataGridView_BackgroundColorChanged(object sender, EventArgs e)
{
SelectionControl.BackColor = this.DataGridView.BackgroundColor;
SetNullImage();
}
private void SelectionControl_LostFocus(object sender, EventArgs e)
{
SelectionControl.Visible = false;
}
private void SetPosition(int ColumnIndex, int RowIndex)
{
Rectangle celrec = this.DataGridView.GetCellDisplayRectangle(ColumnIndex, RowIndex, true);//.Rows[e.RowIndex].Cells[e.ColumnIndex].GetContentBounds();
int x_Offet = (celrec.Width - SelectionControl.Width)/ 2;
int y_Offet = (celrec.Height - SelectionControl.Height)/2;
SelectionControl.Location = new Point(celrec.X + x_Offet, celrec.Y + y_Offet);
SelectionControl.Visible = true;
SelectionControl.RowIndex = RowIndex;
}
private void DataGridView_CellMouseEnter(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == this.Index)
{
SetPosition(e.ColumnIndex, e.RowIndex);
}
}
}

Categories