So I have an array of textboxes dynamically appear (The number of textboxes depends upon how a number from a database). They draw to the screen just fine.
i = 0;
while (i < size)
{
pnlTxtBoxes.Controls.Add(labels[i]);
pnlTxtBoxes.Controls.Add(txtBoxes[i]);
pnlTxtBoxes.Wrap = true;
i++;
}
Like I said, the textboxes appear and the labels are displaying correctly. But when I go to retrieve the text from them, I get the error "Object reference not set to an instance of an object."
i = 0;
while (i < size)
{
values[i] = txtBoxes[i].Text;
txtBoxes[i].Visible = false;
labels[i].Visible = false;
i++;
}
Does anybody have an idea as to why I'm getting this error (and what I can do to fix it)?
EDIT: Here is all of the code. This is just a development DB, so I am not worried about showing the password
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using MySql.Data.MySqlClient;
public partial class dieClearanceCalc : System.Web.UI.Page
{
static string connectionString = "database=localhost;database=matedevdb;uid=dev;pwd=123;";
MySqlConnection con = new MySqlConnection(connectionString);
MySqlCommand cmd = new MySqlCommand("SELECT shapeName FROM tblShapes;");
MySqlDataReader reader;
int size;
TextBox[] txtBoxes;
Label[] labels;
protected void Page_Load(object sender, EventArgs e)
{
cmd.Connection = con;
try
{
con.Open();
reader = cmd.ExecuteReader();
while (reader.Read())
{
shapeSelection.Items.Add(reader.GetString(0));
}
reader.Close();
}
catch (Exception ex)
{
Response.Write("<p style='Color:red'>Error:<br/>" + ex + "</p>");
}
}
protected void shapeSelected(object sender, EventArgs e)
{
string[] labelTxt;
int i = 0;
//Make current elements invisable
lblShape.Visible = false;
shapeSelection.Visible = false;
btnSelectShape.Visible = false;
// find the size of the arrays
cmd.CommandText = "SELECT COUNT(varID) FROM tblVariables WHERE shapeID IN(SELECT shapeID FROM tblShapes WHERE shapeName= '" + shapeSelection.SelectedValue + "')";
reader = cmd.ExecuteReader();
if (reader.Read())
{
size = reader.GetInt32(0);
}
reader.Close();
labelTxt = new string[size];
labels = new Label[size];
txtBoxes = new TextBox[size];
// gather the labels from the db
cmd.CommandText = "SELECT varDesc FROM tblVariables WHERE shapeID IN(SELECT shapeID FROM tblShapes WHERE shapeName= '" + shapeSelection.SelectedValue + "')";
reader = cmd.ExecuteReader();
i = 0;
while (reader.Read())
{
labelTxt[i] = reader.GetString("varDesc");
i++;
}
reader.Close();
i = 0;
while (i < size)
{
labels[i] = new Label();
txtBoxes[i] = new TextBox();
labels[i].Text = labelTxt[i];
i++;
}
i = 0;
while (i < size)
{
pnlTxtBoxes.Controls.Add(labels[i]);
pnlTxtBoxes.Controls.Add(txtBoxes[i]);
pnlTxtBoxes.Wrap = true;
i++;
}
btnSendData.Visible = true;
//Response.Write(size); test to see if the size variable is working
Response.Write(size);
}
protected void calc(object sender, EventArgs e)
{
//declarations
formula diagonal, periphery;
string dFormula = "", pFormula = "";
string[] variables;
string[] values;
int i = 0;
//end of declarations
// This value must be retrievd again, because somewhere size is getting a value of 0
cmd.CommandText = "SELECT COUNT(varID) FROM tblVariables WHERE shapeID IN(SELECT shapeID FROM tblShapes WHERE shapeName= '" + shapeSelection.SelectedValue + "')";
reader = cmd.ExecuteReader();
if (reader.Read())
{
size = reader.GetInt32(0);
}
reader.Close();
variables = new string[size];
values = new string[size];
i = 0;
while (i < size)
{
values[i] = txtBoxes[i].Text;
txtBoxes[i].Visible = false;
labels[i].Visible = false;
i++;
}
btnSendData.Visible = false;
// retrieve the diagonal formula from the db
cmd.CommandText = "SELECT diagonalFormula, peripheryFormula FROM tblShapes WHERE shapeName='" + shapeSelection.SelectedValue + "'";
reader = cmd.ExecuteReader();
while (reader.Read())
{
dFormula = reader.GetString("diagonalFormula");
pFormula = reader.GetString("peripheryFormula");
}
reader.Close();
Response.Write(size);
// gather the variable names from the db
cmd.CommandText = "SELECT varName FROM tblVariables WHERE shapeID IN(SELECT shapeID FROM tblShapes WHERE shapeName= '" + shapeSelection.SelectedValue + "')";
reader = cmd.ExecuteReader();
while (reader.Read())
{
variables[i] = reader.GetString("varName");
i++;
}
reader.Close();
con.Close();
diagonal = new formula(dFormula, variables, values);
periphery = new formula(pFormula, variables, values);
txtDiagonal.Visible = true;
txtPeriphery.Visible = true;
txtDiagonal.Text = diagonal.getEquation();
txtPeriphery.Text = periphery.getEquation();
}
public static double Evaluate(string expression)
{
System.Data.DataTable table = new System.Data.DataTable();
table.Columns.Add("expression", string.Empty.GetType(), expression);
System.Data.DataRow row = table.NewRow();
table.Rows.Add(row);
return double.Parse((string)row["expression"]);
}
}
I reckon you initialize the labels and txtBoxes in if IsPostBack block and don't save it in ViewState or Session.
Edit:
saw your code labels and txtBoxes was initialized in shapeSelected method. same problem will happen: they are lost between postback.
So they are empty in event handler when postback because whole Page object was re-created when postback. Asp.net runtime helps to load content from ViewState for control.But for class member variable you have to maintain by yourself.like:
public string NavigateUrl
{
get
{
string text = (string) ViewState["NavigateUrl"];
if (text != null)
return text;
else
return string.Empty;
}
set
{
ViewState["NavigateUrl"] = value;
}
}
Above code comes from:
Understanding ASP.NET View State
http://msdn.microsoft.com/en-us/library/ms972976.aspx
The article also introduces View State and Dynamically Added Controls
An important thing to remember when programming with ASP.NET is that your whole object model on a page gets created with every web request again and again. This means that if you add some controls to you page dynamically in an event that does not happen each page load they are not going to survive the postback if you don't add them again somehow.
You can read about Asp.Net page Life Cycle here: http://msdn.microsoft.com/en-us/library/ms178472.aspx
I don't think there is a standard way to solve your problem, but what you are trying to do can be achieved in several ways. One was already mentioned to you - usage of ViewState. Another one would be hitting database on each post back, and making sure you are recreating the controls each time the page is served. One more way is to somehow encode the data that is required for recreating your controls and make sure that they are passed with each post back. The latter is essentially what ViewState does, but you can do it more efficiently if you want to reduce the size of you ViewState, and thus size in bytes of your postback and page.
Without seeing more code, I can only guess that the problem lies with where you populate the txtBoxes[] array. Make sure there are no null values in that array.
Related
i would like to create an id generator based on their department selected from the dropdownlist. lets say my ddl has 3 departments (A,B,C) and when generating an id it will be A20181001 and then A20181002 upon submission but when i pick B from the ddl after sending A20181001 to the database, it will be B20181001.
so far i have created the code for the increment for the id without the departments. here is the code i did so far. (I used the date for today so the 20181001 is just an example):
void getMRF_No()
{
string year = DateTime.Now.Date.ToString("yyyyMMdd");
int mrf = 0;
int i;
string a;
//string x = Request.QueryString["BUnit"];
string mrfNo = "";
database db = new database();
string conn = dbe.BU();
SqlConnection connUser = new SqlConnection(conn);
SqlCommand cmd = connUser.CreateCommand();
SqlDataReader sdr = null;
string query = "SELECT TOP 1 MRF_NO FROM incMRF ORDER BY MRF_NO DESC";
connUser.Open();
cmd.CommandText = query;
sdr = cmd.ExecuteReader();
while (sdr.Read())
{
mrfNo = sdr.GetInt32(0).ToString();
}
if (mrfNo == "")
{
mrfNo = Convert.ToString(year) + "" + 00;
}
mrf += 0;
i = Convert.ToInt32(mrfNo) + 1;
a = i.ToString();
txtMRFNo.Text = a;
connUser.Close();
}
any help to improve this code will be helpful. thank you :)
EDIT:
here is the dropdown list code:
void SelectBU()
{
string database = dbe.BU ();
using (SqlConnection con = new SqlConnection(database))
{
con.Open();
string query = "select BUnit from BusinessUnit";
using (SqlDataAdapter sda = new SqlDataAdapter(query, con))
{
DataSet ds = new DataSet();
sda.Fill(ds, "BUnit");
ddlBu.DataSource = ds;
ddlBu.DataTextField = "BUnit";
ddlBu.DataValueField = "BUnit";
ddlBu.DataBind();
selectOption(ddlBu, "Select Dept");
}
con.Close();
}
}
EDIT2: I will state what im searching for here incase some doesnt know or understand. What i want is upon selecting a department from a dropdownlist, for example i picked A. the textbox show show A2018102201. if i select B it should show B2018102201 and if its C then c2018102201. and it will change its number once i submit it to a database and a new form loads. So if A2018102201 is already in the database, then the text shown in the text box will be A2018102202. BUT if i select B then the textbox will show B2018102201 since it does not exist in the database yet.
First you should get max ID, then increase the numeric part of your Id, and If this is a multi-user application, you have to lock your table, because it might create many ID duplication, Therefore I'm not recommend to create ID like this on c#, it is better to create a Sequence on SQL server. but I wrote this sample for you, just call it with proper value.
static string getMRF_No(string prefixCharFromDropDownList)
{
string year = DateTime.Now.Date.ToString("yyyyMMdd");
string mrfNo = "";
SqlConnection connUser = new SqlConnection("Server=130.185.76.162;Database=StackOverflow;UID=sa;PWD=$1#mssqlICW;connect timeout=10000");
SqlCommand cmd = new SqlCommand(
$"SELECT MAX(MRF_NO) as MaxID FROM incMRF where MRF_NO like '{prefixCharFromDropDownList}%'"
,connUser
);
connUser.Open();
SqlDataReader sdr = cmd.ExecuteReader();
while (sdr.Read())
{
mrfNo = sdr["MaxID"].ToString();
}
if (mrfNo == "")
{
mrfNo = prefixCharFromDropDownList + year + "000";
}
else
{
mrfNo = prefixCharFromDropDownList + (long.Parse(mrfNo.Substring(1)) + 1).ToString().PadLeft(2);
}
sdr.Close();
cmd = new SqlCommand($"INSERT INTO incMRF (MRF_NO) values ('{mrfNo}')",connUser);
cmd.ExecuteNonQuery();
connUser.Close();
//txtMRFNo.Text = prefixCharFromDropDownList + i.ToString();
return mrfNo;
}
I call this method on a console application as test.
static void Main(string[] args)
{
// send dropdown (selected char) as prefix to method
var newAId = getMRF_No("A");
var newAnotherAId = getMRF_No("A");
var newBId = getMRF_No("B");
var newAnotherAId2 = getMRF_No("A");
Console.ReadKey();
}
I am using windows form to build an application using datagridview. Every data grid contains an empty row at the top and I suspect that it is the way that I am populating them but as I am coming to the end, I am reluctant to change any of my code as I am a beginner.
Is there a simple way to check if a row if empty, then set that to not visible?
The code that I am using:
private void displayInGrid_Customers(string sqlcmd)
{
customersDataGridView.Rows.Clear();
connect.Open();
command.Connection = connect;
command.CommandText = sqlcmd;
reader = command.ExecuteReader();
customersDataGridView.Rows.Add();
while (reader.Read())
{
DataGridViewRow rowadd = (DataGridViewRow)customersDataGridView.Rows[0].Clone();
rowadd.Cells[0].Value = reader["Customer_ID"].ToString();
rowadd.Cells[1].Value = reader["Forename"].ToString();
rowadd.Cells[2].Value = reader["Surname"].ToString();
rowadd.Cells[3].Value = reader["Address"].ToString();
rowadd.Cells[4].Value = reader["Town"].ToString();
rowadd.Cells[5].Value = reader["Postcode"].ToString();
rowadd.Cells[6].Value = reader["Date_Of_Birth"].ToString();
rowadd.Cells[7].Value = reader["Phone_Number"].ToString();
rowadd.Cells[8].Value = reader["Email"].ToString();
rowadd.Cells[9].Value = reader["Current_Rental"].ToString();
this.customersDataGridView.AllowUserToAddRows = false;
customersDataGridView.Rows.Add(rowadd);
}
reader.Close();
connect.Close();
}
private void button_view_all_customers_Click(object sender, EventArgs e)
{
command.CommandText = "SELECT CUSTOMERS.Customer_ID, CUSTOMERS.Forename, CUSTOMERS.Surname, CUSTOMERS.Address, "
+ "CUSTOMERS.Town, CUSTOMERS.Postcode, CUSTOMERS.Date_Of_Birth, CUSTOMERS.Phone_Number, CUSTOMERS.Email, CUSTOMERS.Current_Rental "
+ "from CUSTOMERS LEFT JOIN STOCK ON CUSTOMERS.Current_Rental = STOCK.Product_ID";
string cmd = command.CommandText;
displayInGrid_Customers(cmd);
}
You could use the IsNullOrWhiteSpace. But before that, you have to check your sql statement, why you have empty rows result.
while (reader.Read())
{
DataGridViewRow rowadd = (DataGridViewRow)customersDataGridView.Rows[0].Clone();
if (!string.IsNullOrWhiteSpace(reader["Customer_ID"].ToString()))
{
rowadd.Cells[0].Value = reader["Customer_ID"].ToString();
//Others Stuff
//...
this.customersDataGridView.AllowUserToAddRows = false;
customersDataGridView.Rows.Add(rowadd);
}
}
Respected Users,
I am extracting data using data set.
I want to put value in textbox. But value is not comming.
I have following Code
try
{
da = new SqlDataAdapter("select ID from Customer where Name='" + gvBkPendingSearch.SelectedRows[0].Cells[1].Value.ToString() + "'",con);
DataSet ds = new DataSet();
da.Fill(ds);
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
txtCustomerID.Text = ds.Tables[0].Rows[0].ToString();
}
catch (Exception ex)
{
}
finally
{
}
txtCustomerID is my textbox.
It is capturing value as>>>>>System.Data.DataRow
Error is in txtCustomerID.Text = ds.Tables[0].Rows[0].ToString();
but i am not able to understand it.
Please help me.
change it like this
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
txtCustomerID.Text = ds.Tables[0].Rows[i]["ID"].ToString();
The mistake you are doing is, you are accessing this
ds.Tables[0].Rows[0].ToString();
means 0th row, the whole row!! not the column value
And the datatable row is System.Data.DataRow in .Net
You need to select the column:
txtCustomerID.Text = ds.Tables[0].Rows[i][0].ToString();
Also note that you are overwriting the value of the textbox on each iteration of the loop. So what you will end up with is the ID of the last record in this textbox.
Also your query seems vulnerable to SQL injection. Personally I would recommend you scraping the DataSets in favor of an ORM or even plain old ADO.NET:
public static IEnumerable<int> GetIds(string name)
{
using (var conn = new SqlConnection("Your connection string comes here"))
using (var cmd = conn.CreateCommand())
{
conn.Open();
cmd.CommandText = "select ID from Customer where Name=#Name";
cmd.Parameters.AddWithValue("#Name", name);
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
yield return reader.GetInt32(reader.GetOrdinal("ID"));
}
}
}
}
And now you could happily use this function:
string name = gvBkPendingSearch.SelectedRows[0].Cells[1].Value.ToString();
int id = GetIds(name).FirstOrDefault();
txtCustomerID.Text = id.ToString();
I've a situation here . I haven't written the code , as I don't have the idea even to kick it off!. I've 10 textboxes and a button , so when I finish typing into only 3 I'll use only three as the values I'm parsing into these textboxes go into the database.I'm planning to write a query in a for loop and execute it, so that only the text boxes which have value get into the database.
for(int i=0;i<9;i++)
{
string sql = "Insert Into exprmnt(docid,itemid,doctitle,itemcontent)values("+int.Parse(label6.Text)+","+i+",'"+label5.Text+"','"+textBox[i].Text+"')";
}
OleDbCommand cmd = new OleDbCommand(sql,con);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
this is something that I'd want to happen , it's okay if I've empty 'itemcontent' against some itemid 'i'which happens when I save all the text boxes including the ones that don't have any text keyed in.
To loop through textBox you can create an array of textBoxes you want to loop through:
TextBox[] tbs = {textBox1, textBox2, textBox3}; //put all into this array
for(int i = 0; i<tbs.Length; i++)
{
//use each textBox in here:
string text = tbs[0].Text; //this is an example of how to get the Text property of each textBox from array
}
For what it's worth, you can use Linq to find the filled textboxes. You're open for SQL-Injection. Use parameters instead of string concatenation:
int docid = int.Parse(label6.Text);
String doctitle = label5.Text;
var filledTextBoxes = this.Controls
.OfType<TextBox>()
.Select((txt,i) => new { Textbox = txt, Index = i })
.Where(x => x.Textbox.Text.Length != 0);
if(filledTextBoxes.Any())
{
using (OleDbConnection connection = new OleDbConnection(connectionString))
{
const String sql = "Insert Into exprmnt(docid,itemid,doctitle,itemcontent)values(#docid, #itemid, #doctitle, #itemcontent)";
connection.Open();
foreach(var txt in filledTextBoxes)
{
OledDbCommand cmd = new OledDbCommand(sql, connection);
// Set the parameters.
cmd.Parameters.Add(
"#docid", OleDbType.Integer).Value = docid;
cmd.Parameters.Add(
"#doctitle", OleDbType.VarChar, 50).Value = doctitle;
cmd.Parameters.Add(
"#itemid", OleDbType.Integer).Value = txt.Index;
cmd.Parameters.Add(
"#itemcontent", OleDbType.VarChar, 100).Value = txt.Textbox.Text;
try
{
int affectedRecords = cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
} // The connection is automatically closed when the code exits the using block.
}
Note that i've used the using-statement to ensure that the connection gets disposed(closed).
It worked finally!!!
#yogi thanks!
the code that worked is
List<TextBox> textBoxList = new List<TextBox>();
textBoxList.Add(new TextBox { Text = textBox1.Text });
textBoxList.Add(new TextBox { Text = textBox2.Text });
textBoxList.Add(new TextBox { Text = textBox3.Text });
textBoxList.Add(new TextBox { Text = textBox4.Text });
for (int n = 1; n<4; n++)
{
string sql = "Insert Into exprmnt (docid,itemid,doctitle,itemcontent) values(" + int.Parse(label6.Text) + "," + n + ",'" + label5.Text + "','" + textBoxList[n].Text+ "')";
OleDbCommand cmd = new OleDbCommand(sql, connection);
connection.Open();
cmd.ExecuteNonQuery();
connection.Close();
}
}
Add your textbox controls to a list.. then loop over the list.
List<TextBox> textBoxList = new List<TextBox>();
for (int i = 0; i < textBoxList.Count; i++) {
// .. do your thing here, using textBoxList[i].Text for the value in the textbox
}
Also, as Tim Schmelter pointed out.. you're open for SQL injection when concatenating your queries like that.
so I'm trying to store values in an array of Lists in C# winForms. In the for loop in which I make the sql statment, everything works fine: the message box outputs a different medication name each time.
for (int i = 0; i < numberOfMeds; i++)
{
queryStr = "select * from biological where medication_name = '" + med_names[i] + "' and patient_id = " + patientID.patient_id;
using (var conn = new SqlConnection(connStr))
using (var cmd = new SqlCommand(queryStr, conn))
{
conn.Open();
using (SqlDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
medObject.medication_date = (DateTime)rdr["patient_history_date_bio"];
medObject.medication_name = rdr["medication_name"].ToString();
medObject.medication_dose = Convert.ToInt32(rdr["medication_dose"]);
medsList[i].Add(medObject);
}
}
conn.Close();
MedicationTimelineClass medObjectx = medsList[i][0] as MedicationTimelineClass;
MessageBox.Show(medObjectx.medication_name);
}
}
but then, when I take the message box code out of the loop, meaning that the array of Lists is supposed to be populated, I always get the same value: the last value entered. the same medication name, no matter what number I put between those brackets. It's like if the whole array of Lists is populated with the same data.
for (int i = 0; i < numberOfMeds; i++)
{
queryStr = "select * from biological where medication_name = '" + med_names[i] + "' and patient_id = " + patientID.patient_id;
using (var conn = new SqlConnection(connStr))
using (var cmd = new SqlCommand(queryStr, conn))
{
conn.Open();
using (SqlDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
medObject.medication_date = (DateTime)rdr["patient_history_date_bio"];
medObject.medication_name = rdr["medication_name"].ToString();
medObject.medication_dose = Convert.ToInt32(rdr["medication_dose"]);
medsList[i].Add(medObject);
}
}
conn.Close();
}
}
MedicationTimelineClass medObjectx = medsList[0][0] as MedicationTimelineClass;
MessageBox.Show(medObjectx.medication_name);
what's going on here?
It looks like you are reusing the same MedicationTimelineClass object inside your loop. Remember that your class is a reference type. You are basically adding the same reference to your list and updating the values of the properties stored in the object at that reference. Ultimately, all of the "items" in your list refer to the same object.
Instantiate a new MedicationTimelineClass object with each iteration and then add that new object to your list.
In the "while (rdr.Read())" loop, you're just adding the same object (medObject) to the list each time. The list is being populated with the same object, over and over again.