I have a drop down list on one form that populates a puzzle id code from a sql table.
when the user selects a puzzle code say "puzzle2" i want the next form(play:Form) to display this puzzle. At the moment i can only get it to display the 1st puzzle "puzzle1" on the page.
The database consists of puzzleID which is the puzzle type and puzzle which is the puzzle question itself.
public partial class Play : Form
{
public Play()
{
InitializeComponent();
SqlConnection conn = new SqlConnection("Data Source=LAURA-PC;Initial Catalog=Sudoku;Integrated Security=True");
conn.Open();
SqlCommand command = conn.CreateCommand();
command.CommandText = "Select puzzle from Puzzle";
command.CommandType = CommandType.Text;
SqlDataReader reader = command.ExecuteReader();
if (reader.Read())
{
string[] tokens = ((string)reader[0]).Split(';');
textBox1.Text = tokens[0];
textBox2.Text = tokens[1];
textBox3.Text = tokens[2];
textBox4.Text = tokens[3];
textBox5.Text = tokens[4];
textBox6.Text = tokens[5];
textBox7.Text = tokens[6];
textBox8.Text = tokens[7];
textBox9.Text = tokens[8];
textBox10.Text = tokens[9];
textBox11.Text = tokens[10];
textBox12.Text = tokens[11];
textBox13.Text = tokens[12];
textBox14.Text = tokens[13];
textBox15.Text = tokens[14];
textBox16.Text = tokens[15];
}
conn.Close();
}
I know i need to implement some sort of of global variable from the drop down list in the previous form and then try filter that variable into Where statement? But im having no luck.
Thanks
You can make an static class as a common place to share objects. All classes can see this class and use its members.
public static class CommonClass
{
public static String puzzleCode ;
}
Also you can have a property on the second form to accept the puzzle id. Like this :
public class SecondForm : Form
{
private String _puzzleId ;
public String PuzzleId
{
get { return _puzzleId ; }
set { _puzzleId = value ; }
}
}
1. Passing variable to form.
Play frmPlay = new Play(puzzleId);
frmPlay.Show();
your Play class will be changed by this
public Play(int puzzleId)
{
//Unchanged code
command.CommandText = "Select puzzle from Puzzle where puzzleId = "+puzzleId;
//Unchanged code
}
2. Passing data through delegate
Add a delegate signature to form1 as below:
public delegate void delPassData(int puzzleId);
Play frmPlay= new Play ();
delPassData del=new delPassData(frmPlay.SetPuzzleId);
del( Convert.ToInt32(cmBxPuzzleId.SelectedValue));
frmPlay.Show();
**In Play form write this code**
private int m_PuzzleId;
public void SetPuzzleId(int puzzleId )
{
m_PuzzleId = puzzuleId;
}
Related
My issue can seem so trivial, but unfortunately I don't know how to solve that problem.
There's one table in one database. I have to add the data with clicking on the button to that table. When user clicks on the button, he's getting to some form where he/she can input the data. At the first time it would be good if I am able to input: id, kind of service, price. I've decided to create a new class where I would content all variables including these three variables. These variable are public.
Also I've decided to read the text from the textBoxes and to write this information to the variables of that class. In the second form there are 2 buttons. "Ok" and "Cancel". And I have decided to use ShowDialog.
I'm capable to output the table from the database to the DataGridView, but I am not well-aware how to add the data to my table and showcase that successfully in the datagridview after the inserting.
My class:
public class AllDataDB
{
public int id_serv;
public double price;
public string name;
}
The second form:
public partial class TypeService : Form
{
public AllDataDB Class;
public TypeService(AllDataDB t)
{
Class = t;
InitializeComponent();
}
private void button2_Click(object sender, EventArgs e)
{
this.Close();
}
private void button1_Click(object sender, EventArgs e)
{
AllDataDB Class = new AllDataDB();
Class.id_serv = Convert.ToInt32(textBox3.Text);
Class.name = NameService.Text;
Class.price = Convert.ToDouble(PriceService.Text);
this.DialogResult = DialogResult.OK;
this.Close();
}
}
The work of the button calling the form and the query:
private void NewServe_Click(object sender, EventArgs e)
{
AllDataDB Class = new AllDataDB();
TypeService form = new TypeService(Class);
if (form.ShowDialog() == DialogResult.OK)
{ // відповідно до класу створюється новий запис. INSERT.
SqlConnection Con = new SqlConnection(connectionString);
Con.Open();
string Que = "INSERT INTO type_service " +
"VALUES(" + Class.id_serv + " ,'" + Class.name +
"' ," + Class.price + " );" +
"SELECT * FROM type_service";
SqlCommand cmd = new SqlCommand(Que, Con);
cmd.ExecuteNonQuery();
Con.Close();
SqlDataAdapter sqlDa = new SqlDataAdapter("SELECT * FROM type_service", Con);
DataTable d = new DataTable();
sqlDa.Fill(d);
dataGridView3.AutoGenerateColumns = false;
dataGridView3.DataSource = d;
}
}
There are many problems in the code shown. The most important ones are the way in which you read the values and how do you try to insert in the data. Inside the form TypeService you create a new instance of the AllDataDB class where you store the results. This instance is no more the one you have passed in input, so you need to read the values from the instance created by the TypeService form (stored in the global field Class). The second problem is the string concatenation of your values. This is a well known problem leading to parsing problems and sql injection. It is fixed by a parameterized query as shown below
private void NewServe_Click(object sender, EventArgs e)
{
// Do no pass an instance of Class here, just pass null
// or remove it at all if you don't plan to reuse the form for updating
TypeService form = new TypeService(null);
if (form.ShowDialog() == DialogResult.OK)
{
// Add the using statement to ensure a proper release of resources.
using SqlConnection Con = new SqlConnection(connectionString);
Con.Open();
// Parameterized query
string Que = "INSERT INTO type_service VALUES(#id,#name,#price);";
SqlCommand cmd = new SqlCommand(Que, Con);
cmd.Parameters.Add("#id", SqlDbType.Int).Value = form.Class.id_serv;
cmd.Parameters.Add("#name", SqlDbType.NVarChar).Value = form.Class.name;
cmd.Parameters.Add("#price", SqlDbType.Decimal).Value = form.Class.price;
cmd.ExecuteNonQuery();
SqlDataAdapter sqlDa = new SqlDataAdapter("SELECT * FROM type_service", Con);
DataTable d = new DataTable();
sqlDa.Fill(d);
dataGridView3.AutoGenerateColumns = false;
dataGridView3.DataSource = d;
}
}
There are other minor problems. In the TypeService form and in the class AllDataDB you have used global fields instead of the more flexible way of using properties.
public class AllDataDB
{
public int id_serv {get;set;}
public double price {get;set;}
public string name {get;set;}
}
as well
public AllDataDB Class {get;set;}
also, given the null passed to the constructor of the TypeService form you now need to ensure to not use that Class properties without cheching for its null value
Well, this aid was very useful. Thanks. But I've resolved this problem with creating a new 3 variables in the class TypeService. These variables are public too. And that is looking like this:
In the class TypeService:
public int i;
public string n;
public double p;
In the class MainCore:
cmd.Parameters.Add("#id", SqlDbType.Int).Value = form.i;// form.Class.id_serv;
cmd.Parameters.Add("#name", SqlDbType.NVarChar).Value = form.n;//form.Class.name;
cmd.Parameters.Add("#price", SqlDbType.Decimal).Value = form.p; //form.Class.price;
So it works. And I can remove the class AllDataDB, because that is not important and useful now.
Thanks for help.
i'm trying to use my Textbox value from another form to a class to insert items to my database.
I tried creating another instance of my Form1 which is the name of the form I want to get the value from but it returns 0 items to my database when I click my submit button is there anyway to do this?
public void Insert()
{
Form1 mform = new Form1();
string query = "INSERT INTO parts (item_id, description, brand, model, color, quantity) VALUES('0', '"
+ mform.Description.Text
+ "','" + mform.Brand.Text
+ "','" + mform.Model.Text
+ "','" + mform.Color.Text
+ "','" + mform.Quantity.Text + "')";
if (this.OpenConnection() == true)
{
MySqlCommand cmd = new MySqlCommand(query, connection);
cmd.ExecuteNonQuery();
this.CloseConnection();
}
}
When you instantiate a new instance of the Form1() object, you are assuming that the new instance's "Description, Brand, Model, Color and Quantity" TextBox's contains text? The default value of a TextBox.Text is the default value of its string property type, null.
Ideally, you will take the values that the user has populated from the form instance and then pass them into the DB like so:
public void Insert()
{
using (var mform = new Form1())
{
// Ensure that the user entered values...
if (mform.ShowDialog() == DialogResult.Ok)
{
string query = "INSERT INTO parts (item_id, description, brand, model, color, quantity) VALUES('0', '"
+ mform.Description.Text
+ "','" + mform.Brand.Text
+ "','" + mform.Model.Text
+ "','" + mform.Color.Text
+ "','" + mform.Quantity.Text + "')";
if (this.OpenConnection() == true)
{
var cmd = new MySqlCommand(query, connection);
cmd.ExecuteNonQuery();
this.CloseConnection();
}
}
}
}
Additionally, you should avoid inline SQL and instead use stored procedures, or at the very least use SqlParameter's.
No, you cannot access Form1 values in a class by creating new instance. To access textbox values you need to do the following:
Create public property in a class
Assign property with textbox value in some appropriate event (such as TextChanged)
Access property inside class to get textbox value and save it to database.
Example
Class:
public class DataAccess
{
public string IncomingValue { get; set; }
public string SaveToDatabase()
{
string valueToSave = IncomingValue;
// Insert into database
return "Success";
}
}
Form:
DataAccess access = new DataAccess();
private void textBox1_TextChanged(object sender, EventArgs e)
{
access.IncomingValue = textBox1.Text;
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show(access.SaveToDatabase());
}
Also, I would suggest you to use Parametrized Query. This will give you more readability and saves you from SQL injection and confusion.
I am using MySql in Windows Form Application. I want to store the result of a MySqlCommand in a string and then assign the contents of that string to a label control on my Windows form so that the label text will display the result of the MySqlCommand.
I have tried the bottom code but that doesn't work.
public void WhoLogIn()
{
_con.Open();
MySqlCommand NewCommand = new MySqlCommand("select titleandfullname from users where username ='" + Variables.whologin + "';", _con);
//Variables.whologin is a public const string in a class declared in another file.
MySqlDataReader result;
result = NewCommand.ExecuteReader();
string _nameofwhologin;
while (result.Read())
{
_nameofwhologin = result.GetString(0);
}
_nameofwhologin = label2.Text;
}
I would like help on how to achieve this using corrections to the code or the proposal of a different method altogether.
Change your code to this;
public void WhoLogIn()
{
_con.Open();
MySqlCommand NewCommand = new MySqlCommand("select titleandfullname from users where username ='" + Variables.whologin + "';", _con);
//Variables.whologin is a public const string in a class declared in another file.
MySqlDataReader result;
result = NewCommand.ExecuteReader();
string _nameofwhologin;
while (result.Read())
{
_nameofwhologin = result.GetString(0);
}
label2.Text=_nameofwhologin;
}
i will try to make this as simple as possible.
I have a working GUI with SELECT, INSERT, DELETE and UPDATE (CRUD) buttons and I am required to use a helper class and NOT just have the code running behind the buttons ect.
But I have NO IDEA what so EVER on how to even start coding this. I don't understand how I can code an action for a button or a label if i'm working in another class.
I have tried doing "ClassNameHere: Form1" but I get an error:
lblInfo is inacessible due to its protection level
cmbTable is inaccessible due to its protection level
I have googled that and tried changing classes to public and not public ect ect to no avail.
So I have to get this code (this is just the SELECTquery)
private void fillcomboBox()
{
try
{
conn = new MySqlConnection(connstring);
conn.Open();
MySqlCommand myCommand = new MySqlCommand("SELECT * FROM person", conn);
MySqlDataReader myReader;
myReader = myCommand.ExecuteReader();
cmbTable.Items.Clear();
while (myReader.Read())
{
cmbTable.Items.Add(myReader["personID"] + " | " + myReader["firstName"] + " | " + myReader["lastName"] + " | " + myReader["address"] + " | " + myReader["phoneNumber"] + " | " + myReader["postCode"] + " | " + myReader["dateOfBirth"]);
}
}
catch (Exception err)
{//handle the error with a message
lblInfo.Text = " Error reading the database.";
lblInfo.Text += err.Message; ;
}
finally
{
}
}
To work in a different class (the helper class) and be linked to the form so that it works but is not behind the buttons...I hope that makes sense.
But like I said, I have no clue on how to even start coding this.
I would love ANY input, anything at all.
Thank you.
Make a method return a List of strings from your database query and put this method in antoher class (e.g. called SQLHelper). You can put all your SQL related methods here. Make the return types independant from SQL specific classes. Like a list of strings, specific person objects, whatsoever. Make this SQL helper class a member of your Form class and call it's methods when you need to. Use it's return values to do the stuff you have to do.
public class SQLHelper
{
public IList<Person> GetPersons()
{
try
{
var result = new List<Person>();
conn = new MySqlConnection(connstring);
conn.Open();
MySqlCommand myCommand = new MySqlCommand("SELECT * FROM person", conn);
MySqlDataReader myReader;
myReader = myCommand.ExecuteReader();
while (myReader.Read())
{
result.add(new Person(){ID = myReader["personID"], ...});
}
return result;
}
catch
{
return null;
}
}
}
public class Person
{
public string ID {get;set;}
public string FirstName {get;set;}
public string LastName {get;set;}
public string Address {get;set;}
public string PhoneNumber {get;set;}
public string PostCode {get;set;}
public string DateOfBirth {get;set;}
public override string ToString()
{
return ID + " | " + FirstName + " | " + "...";
}
}
private void fillcomboBox()
{
cmbTable.Items.Clear();
var sqlHelper = new SQLHelper();
var persons = sqlHelper.GetPersons();
if(persons == null)
{
lblInfo.Text = " Error reading the database.";
return;
}
foreach(var person in persons)
{
cmbTable.Items.Add(person.ToString());
}
}
separate your database access code with UI related code. in your helper method you can write method to retrieve Data what you want to bind the control.
in your UI code behind page, you can call that method in helper class and bind those data to control and if any error, you can show that in label.
I quite new to c# and asp.net so plz tell me if i give you to little info for my question.
When a user is logging in I create an instance of my User object, calling my getcategories method and the redirect then user to another page. Like this:
if (dt.Rows.Count > 0){
user apa = new user();
apa.namn = dt.Rows[0]["FirstName"].ToString() + " " + dt.Rows[0]["LastName"].ToString();
apa.mail = dt.Rows[0]["Email"].ToString();
apa.id = dt.Rows[0]["ID"].ToString();
apa.firstname = dt.Rows[0]["FirstName"].ToString();
apa.lastnamn = dt.Rows[0]["LastName"].ToString();
apa.password = dt.Rows[0]["Password"].ToString();
Session["user"] = apa;
apa.getcategories();
Response.Redirect("visainlagg.aspx");
}
The problem is that I get "object reference not set to an instance of an object"-error on "kategorier[i].Name = dt.Rows[i]["Name"].ToString();" (the first thing that happens in my for loop in User class). I do not understand why :(
This is how the User class looks like:
public string namn;
public string mail;
public string id;
public string firstname;
public string lastname;
public string password;
public string constr = "secret";
public Post[] poster;
public anvcateg[] kategorier;
public int antalKategorier;
public void getcategories() {
SqlConnection conn = new SqlConnection();
conn.ConnectionString = constr;
SqlCommand com = new SqlCommand();
com.Connection = conn;
com.CommandText = "SELECT * FROM Category WHERE Author= '" + id + "'";
SqlDataAdapter adp = new SqlDataAdapter();
adp.SelectCommand = com;
DataTable dt = new DataTable();
adp.Fill(dt);
antalKategorier = dt.Rows.Count;
kategorier = new anvcateg[dt.Rows.Count];
for (int i = 0; i < dt.Rows.Count; i++)
{
kategorier[i].Name = dt.Rows[i]["Name"].ToString();
kategorier[i].ID = dt.Rows[i]["ID"].ToString();
kategorier[i].Description = dt.Rows[i]["Description"].ToString();
kategorier[i].Author = dt.Rows[i]["Author"].ToString();
}
}
the anvcateg class that getcategories() is using looks like this:
public class anvcateg
{
public string ID;
public string Name;
public string Description;
public string Author;
kategorier is an array of anvcateg
You initialized the array here:
kategorier = new anvcateg[dt.Rows.Count];
But you have to create an instance of anvcateg to add to your array)
for (int i = 0; i < dt.Rows.Count; i++)
{
kategorier[i] = new anvcateg()
{
ID = dt.Rows[i]["ID"].ToString(),
Author = dt.Rows[i]["Author"].ToString(),
Description = dt.Rows[i]["Description"].ToString(),
Name = dt.Rows[i]["Name"].ToString()
};
}
Your array contains all nulls - you have not created any objects. You have created an empty array. A quick fix would be:
kategorier[i] = new anvcateg();
at the start of each iteration.
For info, your current code is risky (SQL injection), doesn't clean up after itself, and unnecessarily complicated. Here's the same via "dapper":
using(var conn = new SqlConnection(constr)) {
conn.Open();
var data = conn.Query<anvcateg>(
"SELECT * FROM Category WHERE Author=#id",
new { id }).ToList();
}
(or ToArray() if you prefer)
This does all the mapping internally, cleans up the connection, and safely parameterises the "id" avoiding injection attacks. And no DataTable to be seen.
Your question is not quite clear, try to find the code "kategorier[i].Name = dt.Rows[i]["Name"].ToString();" but could not found it. if you can post your code which contain these lines then it would be easy to answer you.
Anyway, there may be the following reason of this error:
Either dt.Rows[i]["Name"] is null and you are trying to convert it into string by using .ToString(), change this to Convert.ToString(dt.Rows[i]["Name"])
check you have defined "kategorier" as an array or you can use the List kategorier = new List kategoriers();
Otherwise your code looks fine