Get value from programmatically created TextBox in C# - c#

I got this itching problem and I cant get the code to work
How can i read the value from the TextBox when the form is posted?
Some code...
protected override void CreateChildControls() {
base.CreateChildControls();
TextBox queryBox = new TextBox();
queryBox.ID = "querybox";
queryBox.ToolTip = "Enter your query here and press submit";
Controls.Add(queryBox);
Button queryButton = new Button();
queryButton.UseSubmitBehavior = false;
queryButton.ID = "querybutton";
Controls.Add(queryButton);
if (Page.IsPostBack == true) {
try {
string query = querybox.Text;
DataGrid dataGrid = new DataGrid();
dataGrid.DataSource = Camelot.SharePointConnector.Data.Helper.ExecuteDataTable(query, connectionString);
dataGrid.DataBind();
Controls.Add(dataGrid);
} catch (Exception a) {
Controls.Add(new LiteralControl(a.Message));
} // try
} // if
} // void
I've shortened the code a bit but you see the idea, its the string query = querybox.text that wont work. I've tried with a few different variants, i.e.
TextBox querybox = (TextBox)FindControl("querybox");
string query = querybox.Text;
But no...
Any tips is appreciated!
Thanks

The problem is that your controls are not populated with values from the ViewState in CreateChildControls. I'd recommend using a click event handler on your button.
Update your button code:
Button queryButton = new Button();
queryButton.UseSubmitBehavior = false;
queryButton.ID = "querybutton";
queryButton.Text = "Query";
queryButton.Click += new EventHandler(queryButton_Click);
Controls.Add(queryButton);
Then, write the click event handler:
void queryButton_Click(object sender, EventArgs e)
{
TextBox querybox = this.FindControl("querybox") as TextBox;
try
{
string query = querybox.Text;
DataGrid dataGrid = new DataGrid();
dataGrid.DataSource = Camelot.SharePointConnector.Data.Helper.ExecuteDataTable(query, connectionString);
dataGrid.DataBind();
Controls.Add(dataGrid);
}
catch (Exception a)
{
Controls.Add(new LiteralControl(a.Message));
} // try
}

Try stepping through and looking into the Request.Form["name"] object.
What is probably happening is your Text box may not be being saved properly in the view state, but if it is a valid form object when a post back occurs it should exist within the Request.Form object, the ID may be different so you may have to do some searching.

Trikks,
I've found this which might help you.
Try looking for the text box in the load event (after checking its a postback!) rather than CreateChildControls which will separate your code out and make things a bit clearer. As Mmerrell says the id will probably get altered too, depending on the rest of the page.

You get the null reference exception because you do a
TextBox querybox = (TextBox)FindControl("querybox");
on the PAGE object.
So you're searching for page->querybox
But the textbox is in page->form1->querybox.
You need to write a recursive findcontrol, because querybox is a control in the form1 control, not a control in page.
public static Control FindControlRecursive(Control container, string name)
{
if ((container.ID != null) && (container.ID.Equals(name)))
return container;
foreach (Control ctrl in container.Controls)
{
Control foundCtrl = FindControlRecursive(ctrl, name);
if (foundCtrl != null)
return foundCtrl;
}
return null;
}

It might help to wrap the code in a !Page.IsPostBack check. Otherwise the textboxes get recreated on postback and delete any information.
if (!Page.IspostBack) {
TextBox queryBox = new TextBox();
queryBox.ID = "querybox";
queryBox.ToolTip = "Enter your query here and press submit";
Controls.Add(queryBox);
Button queryButton = new Button();
queryButton.UseSubmitBehavior = false;
queryButton.ID = "querybutton";
Controls.Add(queryButton);
} else {
try {
string query = querybox.Text;
DataGrid dataGrid = new DataGrid();
dataGrid.DataSource = Camelot.SharePointConnector.Data.Helper.ExecuteDataTable(query, connectionString);
dataGrid.DataBind();
Controls.Add(dataGrid);
} catch (Exception a) {
Controls.Add(new LiteralControl(a.Message));
} // try
} // if
Oh and don't trust the user to enter a query on your database.
Your database will crash and burn

Related

C# getting information in the behind form

I have two forms
the first one is FrmReceiveItems from which I can display the second one
FrmItemSearch. In the second one I can choose a certain item to add to a DataGridView in the first form. The problem is that whenever I add an item I will have a new object from the first form. I want all chosen items to be added to the first opened form. I try to test if any object of the first form is opened .. as following:
private void dgv_ItemsSearch_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
try
{
//Connection obj = new Connection();
//Connection.FrmChose = 10;
FrmRecieveItemsVoucher FRI = new FrmRecieveItemsVoucher();
Form frmT = Application.OpenForms["FRI"];
int value = Connection.FrmChose;
if (value == 10)
{
FRI.dataGridView_ItemsVoucher.Rows.Add();
int CurrentRowIndex = FRI.dataGridView_ItemsVoucher.Rows.Count;
FRI.dataGridView_ItemsVoucher.Rows[CurrentRowIndex - 1].Cells[0].Value = dgv_ItemsSearch.CurrentRow.Cells[2].Value;
FRI.dataGridView_ItemsVoucher.Rows[CurrentRowIndex - 1].Cells[1].Value = dgv_ItemsSearch.CurrentRow.Cells[1].Value;
// here I try to test
if (frmT != null)
{
this.Dispose();
}
else
{
FRI.Show();
}
}
else
{
FrmItems frmItems = new FrmItems();
//frmCust.btn_new(sender,e);
string Code = Convert.ToString(dgv_ItemsSearch.CurrentRow.Cells[2].Value);
this.Dispose();
frmItems.Show();
frmItems.Show_Record_data(Code);
}
}
catch (Exception Ex)
{
MessageBox.Show(Ex.Message);
}
}
well there are a lot of ways to achieve this. What I would personally go for is creating a BindingList and setting a ListChanged event on that list that would then trigger a reload in the second form.

How to retain data for dynamically created controls?

I have the following situation:
I have 2 drop down lists (DDL) with auto-postback enabled.
When the user selects something from first DDL, he can choose stuff from 2nd DDL.
When the user selects something from 2nd DDL, I open database (WHERE clause of SQL query is filled with values from DDLs), and dynamically create several text boxes, labels and buttons which I place inside a placeholder.
The problem is: when I click on some of the dynamically created buttons, nothing happens, and I can't retrieve data from dynamically created boxes. Also, placeholder content is lost (all controls).
So my question is: how do I retain data from dynamically created controls on postback?
I have listed a lot of similar articles on this site, and none solves my problem. Another thing is - I can't use view state nor session.
Code is:
public Button btn1 = new Button();
public TextBox txtBoxC1 = new TextBox();
public TextBox txtBoxC2 = new TextBox();
public TextBox txtBoxC3 = new TextBox();
...
...
...
protected void ddl2_SelectedIndexChanged(object sender, EventArgs e)
{
...
...
if some conditions are met:
...
...
String CS4 = ConfigurationManager.ConnectionStrings["connStringName"].ConnectionString;
using (SqlConnection conn4 = new SqlConnection(CS4))
{
SqlCommand cmd4 = new SqlCommand("Select * from table where column1=" +
Convert.ToInt32(ddl2.SelectedValue)+" order by column1", conn4);
conn4.Open();
SqlDataReader rdr = cmd4.ExecuteReader();
while (rdr.Read())
{
txtBoxC1.Text = rdr["column1"].ToString(); txtBoxC1.MaxLength = 3; txtBoxC1.Columns = 3; txtBoxC1.ID = ddl2.SelectedValue + "1";
txtBoxC2.Text = rdr["column2"].ToString(); txtBoxC2.MaxLength = 3; txtBoxC2.Columns = 3; txtBoxC2.ID = ddl2.SelectedValue + "2";
txtBoxC3.Text = rdr["column3"].ToString(); txtBoxC3.MaxLength = 3; txtBoxC3.Columns = 3; txtBoxC3.ID = ddl2.SelectedValue + "3";
btn1.Text = "click me"; btn1.ID = ddl1.SelectedValue; btn1.Click += btn1_Click;
phDynamic.Controls.Add(btn1);
phDynamic.Controls.Add(txtBoxC1);
phDynamic.Controls.Add(txtBoxC2);
phDynamic.Controls.Add(txtBoxC3);
}
}
}
...
...
...
private void btn1_Click(object sender, EventArgs e)
{
Response.Write(txtBoxC1.Text+txtBoxC2.Text+txtBoxC3.Text);
}
So instead of getting back values from my 3 textboxes, I don't get back anything, and I also lose placeholder controls.

Win Form disappears after it is loades with .show()

I have a grid that I want to pop up in a new window. The code I am using is below. The table is populated with the right data all the way through. The only problem is, when the new winform pops up, it immediately disappears. Also, it's not displaying the data in the grid. I can't figure out what I'm doing wrong. Any ideas?
private void gridView1_ShowGridMenu(object sender, DevExpress.XtraGrid.Views.Grid.GridMenuEventArgs e)
{
GridView view = sender as GridView;
GridHitInfo hitInfo = view.CalcHitInfo(e.Point);
if (hitInfo.InRow)
{
var rowData = gridView1.GetRowCellValue(hitInfo.RowHandle, "SP");
string[] rowDataSplit = rowData.ToString().Split(':');
using (frmInterfaceLogSelection form = new frmInterfaceLogSelection(Services))
{
var sql = rowDataSplit[1].ToString();
var ds = Services.RunSql(sql);
var table = ds.FirstTable();
if (table == null)
{
var error = Services.LastSqlResultError;
if (error.Length > 0)
{
MessageBox.Show(error);
}
return;
}
table.AcceptChanges();
this.gridControl1.DataSource = table;
this.gridView1.Columns.BestFitAll();
form.Show();
}
}
}
It's because you are disposing of the form.
The using statement disposes the form after form.Show(), so it disappears.
You likely need to dispose your SQL connection/service connection, rather than your form.
Try using show dialog
form.ShowDialog();

textbox auto complete (Multi Line)

I am making a auto suggestion / complete textbox in C#, i followed below link, but text box isnt showing the suggestions
How to create autosuggest textbox in windows forms?
//-------- Get all distinct description -----------------------------
OleDbCommand command = new OleDbCommand(Queries.qry16, Connection);
OleDbDataReader reader = command.ExecuteReader();
//--------- Storing ------------------------------------
while (reader.Read())
{
namesCollection.Add(reader.GetValue(0).ToString());
}
//----------- Close after use ---------------------------------------
reader.Close();
//----------- Set the auto suggestion in description box ------------
descriptionBox.AutoCompleteMode = AutoCompleteMode.Suggest;
descriptionBox.AutoCompleteSource = AutoCompleteSource.CustomSource;
descriptionBox.AutoCompleteCustomSource = namesCollection;
Here is my code , it is in load function of winform. And the nameCollection initializtion is in constructor... kindly please help to make it working.
I am editing my post rather then creating new... I have tried the my own code in single line textbox and it worked. Now i want the same in multi line... For research i googled more then 2 days trying different codes (one with intelli sense) but it didnt worked as auto suggestion available in textbox. Can any one give me suggestion to code the whole procedure to multi line.. Thank you.
AutoCompleteSource does not work on multiline TextBox controls.
Wich means you need to make it from scratch:
I would make a ListBox to display the content of your autocomplete:
var listBox = new ListBox();
Controls.Add(listBox);
You need eventhandling on your textbox however this is a bit crude, so i would rewrite it to stop the keyupevent at some point:
private void textBox_KeyUp(object sender, KeyEventArgs e)
{
var x = textBox.Left;
var y = textBox.Top + textBox.Height;
var width = textBox.Width + 20;
const int height = 40;
listBox.SetBounds(x, y, width, height );
listBox.KeyDown += listBox_SelectedIndexChanged;
List<string> localList = list.Where(z => z.StartsWith(textBox.Text)).ToList();
if(localList.Any() && !string.IsNullOrEmpty(textBox.Text))
{
listBox.DataSource = localList;
listBox.Show();
listBox.Focus();
}
}
Now all you need is a handler to set the text in your textBox:
void listBox_SelectedIndexChanged(object sender, KeyEventArgs e)
{
if(e.KeyValue == (decimal) Keys.Enter)
{
textBox2.Text = ((ListBox)sender).SelectedItem.ToString();
listBox.Hide();
}
}
Put in null checks where appropriate
You need to add a New Component class by 'Adding New Item'. and then write the code for that class and then add that component wherever required..
Try this code as it works in my case:
AutoCompleteStringCollection MyCollection = new AutoCompleteStringCollection();
while (reader.Read())
{
namesCollection.Add(reader.GetString(0));
}
reader.Close();
descriptionBox.AutoCompleteMode = AutoCompleteMode.Suggest;
descriptionBox.AutoCompleteSource = AutoCompleteSource.CustomSource;
descriptionBox.AutoCompleteCustomSource = namesCollection;
con.Close();
Please check if the reader is getting the desired records..:)
Bit of confusion on the "auto-suggestion" since that is basically auto-complete without the permission from the user to "complete" the text. Nevertheless here are a couple of links you might find helpful:
http://docs.jquery.com/UI/Autocomplete
Autocomplete functionality on a textarea
AutoComplete extender for multi-line Textbox
Scroll down on link #2, a user suggested a jquery solution and compare with link #1. You may find a solution.
Third link is from asp forums, similar question like yours was also answered by a link. You might want to check that out.
Thismay help you solving problem ;
You can change table name. you can change the query to load listbox.
ListBox lbox;
private void IletisimBilgileriDoldur()
{
try
{
string strQuery= "Select adres From tblIletisimBilgileri Where adres <> '';";
veri = new OleDbCommand(strQuery,strConn);
veri.CommandType = CommandType.Text;
if (strConn.State == ConnectionState.Closed) strConn.Open();
oku = veri.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(oku);
oku.Close();
txtAdres.AutoCompleteCustomSource.Clear();
if (dt.Rows.Count >= 0)
{
lbox = new ListBox();
for (int count = 0; count < dt.Rows.Count; count++)
{
lbox.Items.Add(dt.Rows[count]["adres"].ToString());
}
}
txtAdres.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
txtAdres.AutoCompleteSource = AutoCompleteSource.CustomSource;
if (strConn.State == ConnectionState.Open) strConn.Close();
}
catch (Exception)
{
if (strConn.State == ConnectionState.Open) strConn.Close();
}
}
private void txtAdres_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
var x = txtAdres.Left;
var y = txtAdres.Top + txtAdres.Height;
var width = txtAdres.Width;
const int height = 120;
lbox.SetBounds(x, y, width, height);
lbox.KeyDown += lbox_SelectedIndexChanged;
lbox.DoubleClick += lbox_DoubleClick;
gbxAdres.Controls.Add(lbox);
lbox.BringToFront();
lbox.Show();
ActiveControl = txtAdres;
}
void lbox_DoubleClick(object sender, EventArgs e)
{
txtAdres.Text = ((ListBox)sender).SelectedItem.ToString();
lbox.Hide();
}

change controls based on database value

Problem:
I have a value in a database table. This value can either contain a number, or null. If its null I would like to show one group of controls. If its not null I would like to show another group of controls.
Previous Attempts:
I have tried creating the controls in the code behind depending on the value of the database. This worked. However, on postback I get a null reference exception. The control doesn't exist on postback because the page is stateless. I'm building the controls in the page_load handler (depending on the value of the table column). Since I'm creating the controls in the page_load shouldn't they exist on postback?
I also tried recreating the controls in the event handler for the button. I get a "theres already a control with this id" exception (presumably because I already created it in the page_load method).
I read a few posts about how I have to store the controls in a session. This seems like more work than it should be.
Questions:
Am I going about this the wrong way? This seems like it should have been simple but is turning into a mess.
If this is the correct way to do this, Where do I add the session information? I've been reading other posts and I'm kind of lost
Code:
int bookId;
string empName;
protected void Page_Load(object sender, EventArgs e)
{
if(int.TryParse(Request.QueryString["id"], out bookId))
{
//This is where the value in the database comes into play. If its null Book.GetCopyOwner
// returns a string with length 0
empName = Book.GetCopyOwner(bookId, Request.QueryString["owner"]);
if (empName.Trim().Length > 0)
{
CreateReturnControls();
}
else
{
CreateCheckoutControls();
}
}
}
protected void ReturnButton_Click(object sender, EventArgs e)
{
}
protected void CheckOut_Click(object sender, EventArgs e)
{
int bookId;
if (int.TryParse(Request.QueryString["id"], out bookId))
{
TextBox userId = (TextBox)this.Page.FindControl("UserId");
//WHEN I TRY TO USE THE TEXTBOX userId HERE, I GET NULL REFERENCE EXCEPTION
BookCopyStatusNode.Controls.Clear();
CreateReturnControls();
}
}
protected void CopyUpdate_Click(object sender, EventArgs e)
{
}
private void CreateCheckoutControls()
{
TextBox userId = new TextBox();
//userId.Text = "Enter Employee Number";
//userId.Attributes.Add("onclick", "this.value=''; this.onclick=null");
userId.ID = "UserId";
Button checkOut = new Button();
checkOut.Text = "Check Out";
checkOut.Click += new EventHandler(CheckOut_Click);
TableCell firstCell = new TableCell();
firstCell.Controls.Add(userId);
TableCell secondCell = new TableCell();
secondCell.Controls.Add(checkOut);
BookCopyStatusNode.Controls.Add(firstCell);
BookCopyStatusNode.Controls.Add(secondCell);
}
private void CreateReturnControls()
{
Label userMessage = new Label();
userMessage.Text = empName + " has this book checked out.";
Button returnButton = new Button();
returnButton.Text = "Return it";
returnButton.Click += new EventHandler(ReturnButton_Click);
TableCell firstCell = new TableCell();
firstCell.Controls.Add(userMessage);
TableCell secondCell = new TableCell();
secondCell.Controls.Add(returnButton);
BookCopyStatusNode.Controls.Add(firstCell);
BookCopyStatusNode.Controls.Add(secondCell);
}
It looks like you're creating a static set of controls based on the database value. Why not simply have 2 Panels that contain the controls you want and simply set their visibility to true or false:
if (!Page.IsPostBack)
{
if (int.TryParse(Request.QueryString["id"], out bookId))
{
empName = Book.GetCopyOwner(bookId, Request.QueryString["owner"]);
var display = (empName.Trim().Length > 0);
panelReturnControls.Visible = display;
panelCheckoutControls.Visible = !display;
}
}

Categories

Resources