11 Replies - 1016 Views - Last Post: 25 September 2011 - 03:47 AM Rate Topic: -----

#1 Gadge  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 34
  • Joined: 08-April 09

How do I reference the objects / variables in a form?

Posted 17 September 2011 - 03:50 AM

Hi, thanks for looking.

I don't know if I am going about this entirely the wrong way but I have been following tutorials and created a small database application that connects to a SQL database (database of names / jobs).

I have an if statement that activates via a combo box which allows the user to pick which details they want to search on via a drop down box. I did have this initially setup as a method which later called the code within the same form which works perfectly.


What I would like to do is to take my method onto a seperate page (another class?) to tidy up my form. I don't really understand how I reference my buttons etc.. from form1 onto my new class List_Methods:


Extract of what i'm trying to do:

Form1.cs
            if (comboBox1.Text == "First Name")
            {
                List_Methods Firstnameselecton = new List_Methods();

            //  Firstnameselecton();

            }


List_Methods.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SQLDatabase
{
    class List_Methods
    {
            Form1 Form1_Load;
            Form1_Load = new Form1();      
   

        private void Firstnameselecton()
        {
      

            string searchFor = richTextBox4.Text;

            int results = 0;
            DataRow[] returnedRows;

            returnedRows = ds1.Tables["Workers"].Select("first_name like '" + searchFor + "%'");

            results = returnedRows.Length;


            if (results > 0)
            {
                DataRow dr1;
                dr1 = returnedRows[0];

                MessageBox.Show(dr1["first_name"].ToString() + " " + dr1["last_name"].ToString() + ", Job Title: " + dr1["Job_Title"].ToString());
            }
            else
            {
                MessageBox.Show("No Record");
            }
        }


    }
}




Is This A Good Question/Topic? 0
  • +

Replies To: How do I reference the objects / variables in a form?

#2 JackOfAllTrades  Icon User is offline

  • Saucy!
  • member icon

Reputation: 6036
  • View blog
  • Posts: 23,421
  • Joined: 23-August 08

Re: How do I reference the objects / variables in a form?

Posted 17 September 2011 - 04:36 AM

We have some excellent tutorials, like this one, which might be helpful.
Was This Post Helpful? 2
  • +
  • -

#3 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5436
  • View blog
  • Posts: 11,653
  • Joined: 02-June 10

Re: How do I reference the objects / variables in a form?

Posted 17 September 2011 - 06:09 AM

Don't worry, this is a common question.

See FAQ #2


FAQ (Frequently Asked Questions - Updated Sep 2011

Spoiler

Was This Post Helpful? 0
  • +
  • -

#4 Gadge  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 34
  • Joined: 08-April 09

Re: How do I reference the objects / variables in a form?

Posted 18 September 2011 - 02:32 AM

Thanks for the replies.

I think I have been going about this the wrong way since I was really doing this to try and make it neater by putting my methods into another .cs file but I don't think its possible for that other CS file to see the objects on the form as if it was in the same file?

i.e call
textbox.text from my class file?

I think I have alot more reading and tutorals to follow, I'm pretty confused regarding this subject to be honest and don't understand how I can make it work with what i'm trying to do, feel free to edit the example given if you can suggest a better way please.

I think I will start a new project with a new connection string that just displays "connection open" and "connection closed" and try and figure out how to pass that along then expand.
Was This Post Helpful? 0
  • +
  • -

#5 CodingSup3rnatur@l-360  Icon User is online

  • D.I.C Addict
  • member icon

Reputation: 991
  • View blog
  • Posts: 971
  • Joined: 30-September 10

Re: How do I reference the objects / variables in a form?

Posted 18 September 2011 - 03:43 AM

I like the way you are thinking about moving application logic out of the UI class. It is definitely something you should try and do. However, you are thinking about accessing UI controls directly from the List_Methods class. That is not a good idea.

The List_Methods class should not know anything specific about what is on the UI.


Basic Method calls

You can achieve basic interaction between your form and your logic class using simple methods. Here is a generic example:

In this example, I have 1 button called btnProcess, and two textboxes called txtData and txtResult. The idea is that I have a method in a separate class (this class is called Logic, just for this example) that processes data from the txtData textbox. The result of the processing is then displayed in the txtResult textbox.

In that scenario, there is clearly some interaction between the Form1 class and the Logic class (Logic class needs data from UI, and UI needs to retrieve result from the Logic class), so how can we do it?

We simply use methods! Pass the data in to the method in the Logic class, and return the result from that method.

Logic.cs

Spoiler


Now, we have our method to process data separated into a different class, well away from the UI.

Now, in the UI class:


Form1.cs

Spoiler


In the UI class, we create an instance of our Logic class. When we click the button, we want the processing to start. So, we pass the data from the data textbox into the ProcessData() method as a parameter, and that method processes the data and returns the result, of which we put in the result text box.

It could not be more simple! It is just calling a method. The Logic class is completely independent of the UI, and we have removed the responsibility of the processing out of the UI class, leaving it to focus purely on retrieving data from the user, and displaying data.

Other techniques

Using an interface to represent the UI

Sometimes it is perfectly acceptable to pass an instance of the Form1.cs class, and access values on the form directly (just look at the MVP pattern). However, if we do this, it is important that we code to an interface, rather than accessing GUI controls directly.

For example:

The interface representing the view - IView.cs

Spoiler


That now represents our UI.

Form1.cs

Spoiler


Logic.cs

Spoiler


Now, we can see that the Logic class actually contains a reference to the form. This is usually not a good idea. However, as we are using an interface, and accessing the controls indirectly through properties, we still have a decoupled design (we can change around the form's layout, add new controls, take controls away etc without affecting the Logic class.


Using events

This is the concept that Curtis Rutland explained very well in his tutorial linked above. The idea is to raise an event in the Logic class, of which contains the result of the processing. The UI then subscribes to that event, and when the result is ready, it accesses it an updates the UI.

It's a bit awkward in the context of my example scenario, but here is an example:

ResultReadyEventArgs.cs

Spoiler


This class will hold the result of the processing

Logic.cs

Spoiler


This class now processes the data from the UI (that is passed in as a parameter to the ProcessData() method), and raises an event when the result is ready.

Form1.cs

Spoiler


The UI class now subscribes to the ResultReady event in the Logic class. It calls ProcessData(), pasing in the data in the data textbox. The Logic class processes the data, and raises the ResultReady event when it has a result. The logic_ResultReady() method in the UI class in then called, and it grabs the result, and puts it in the results textbox :)


Conclusion

Clearly, in this very simplistic example, the basic methods approach shown in the first example is the way to go. However, each technique has its place in different applications/scenarios, and each technique allows a form of two way communication between the UI and class(es) containing the application logic, whilst keeping the two loosely coupled.

Notice how I never, in any of the examples, access the UI controls directly from the Logic class. Only the parent form class should be able to do this.

So there you go. Three different ways to achieve two way communication between the UI and application logic classes, whilst minimising coupling.

This post has been edited by CodingSup3rnatur@l-360: 18 September 2011 - 04:09 AM

Was This Post Helpful? 3
  • +
  • -

#6 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5436
  • View blog
  • Posts: 11,653
  • Joined: 02-June 10

Re: How do I reference the objects / variables in a form?

Posted 18 September 2011 - 07:12 AM

See FAQ #2 for class-to-class communication tutorials


FAQ (Frequently Asked Questions - Updated Sep 2011

Spoiler

Was This Post Helpful? 0
  • +
  • -

#7 Gadge  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 34
  • Joined: 08-April 09

Re: How do I reference the objects / variables in a form?

Posted 18 September 2011 - 07:27 AM

Very nice post, CodingSup3rnatur@l thanks for taking the time to post that it really helped.

I think I have it now. I added a combobox + an if statement within the button and another class but I think I get the idea behind it. Hopefully I should be able to tidy up my software a bit now :)

Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Basic_Method_calls
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            this.logic = new Logic();
        }


        private readonly Logic logic;
        public string Data
        {
            get { return this.txtData.Text; }
            set { this.txtData.Text = value; }
        }

        public string Result
        {
            get { return this.txtResult.Text; }
            set { this.txtResult.Text = value; }
        }


        private string ProcessData(string data)
        {
            return this.logic.ProcessData(data); //pass data from textbox to 'Logic'
            //class for processing, thus delegating
            //responsibility away from the UI
        }


        private string ProcessData1(string data)
        {
            return this.logic.ProcessData1(data); //pass data from textbox to 'Logic'
            //class for processing, thus delegating
            //responsibility away from the UI
        }


        private void Form1_Load(object sender, EventArgs e)
        {
            //load combo
            comboBox1.Items.Add("1st");
            comboBox1.Items.Add("2nd");      
        }     
        

        private void btnProcess_Click_1(object sender, EventArgs e)
        {

            if (comboBox1.Text == "1st")
            {
                this.Result = this.ProcessData(this.Data);
            }

            if (comboBox1.Text == "2nd")
            {
                this.Result = this.ProcessData1(this.Data);
            }

        }
    
    }
}                



Logic.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Basic_Method_calls
{
    public class Logic
    {
        public string ProcessData(string data)
        {
            //process data from UI here. return result
            //for display in UI.

            int newdata = 5 + 5 + 5 + 5;
                     
           string random = newdata + " " + "this is my string";

            return "Result = " + data + random;
        }


        public string ProcessData1(string data)
        {
            //process data from UI here. return result
            //for display in UI.

           string random = "2nd string";

            return random;
        }
    }
}


Was This Post Helpful? 0
  • +
  • -

#8 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5436
  • View blog
  • Posts: 11,653
  • Joined: 02-June 10

Re: How do I reference the objects / variables in a form?

Posted 18 September 2011 - 07:40 AM

I don't want to throw too much too fast at you.
But you seem to have taken that last concept pretty darn fast and well. Good Job!

The link gave you in post #3 has some good tutorials on events. This would allow one form to notify the other when it was done/read, instead of the caller waiting on the called.

This is a great tutorial on how to Decouple your multi-threaded work from the GUI so forms don't hang.

If you were to adjust your logic above to make use of threads it wouldn't work so linearly. That's not a problem with simple examples like you have here. But when you have larger amounts of processing it might take 2-200 seconds to do the work. When a form is 'sluggish' for even a couple seconds it detracts from the user experience. If your computation takes place on its own thread you won't get that sluggish behavior.

This post has been edited by tlhIn`toq: 18 September 2011 - 07:41 AM

Was This Post Helpful? 1
  • +
  • -

#9 Gadge  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 34
  • Joined: 08-April 09

Re: How do I reference the objects / variables in a form?

Posted 18 September 2011 - 10:32 AM

Thanks for the link, gives me a few ideas and answered a few questions I had brewing regarding future ideaís I had.

At the moment Iím just trying to automate certain parts of my job for me and my colleagues. I think what I need to learn next is how to navigate / allow a user to navigate multiple servers and databases within them in order to run specific queries.
Was This Post Helpful? 0
  • +
  • -

#10 Gadge  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 34
  • Joined: 08-April 09

Re: How do I reference the objects / variables in a form?

Posted 24 September 2011 - 03:34 AM

Hi Guy's

I'm looking for a bit of assistant on how I should be passing input variables to my class i.e I have this application which connects to a database and retrives error logs.

All is working fine if I put a direct number instead of data in the logic class for the SQL where statement, if I assign a local variable but I just cannot figure out how I am supposed to pass it over correctly from the input the user gives

the data variable currently looks to be null so i'm likely doing something silly.


I think this is my issue is?:
        public string Data
        {
            get { return this.txtData.Text; }
            set { this.txtData.Text = value; }
        }




Part of my software in which I am calling the class and trying to pass over the value?

namespace connectionstring
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            this.logic = new Logic();
        }

        private readonly Logic logic;
        public string Data
        {
            get { return this.txtData.Text; }
            set { this.txtData.Text = value; }
        }

        public string Result
        {
            get { return command.CommandText; }
            set { this.command.CommandText = value; }
        }

        private string ProcessData(string data)
        {
            return this.logic.ProcessData(data); //pass data from textbox to 'Logic //class for processing, thus delegating
        }

        //Variables
        string server; string database; string source; string KD; string input1; string input2;

        //CONNECTION STRINGS!!!
        SqlConnection connection = new SqlConnection();   //inital SQL Connection variable
        SqlCommand command = new SqlCommand();
        SqlDataReader reader;     // inialise reader

        private void button1_Click(object sender, EventArgs e)
        {

            if (txtData.Text == string.Empty)
            {
                MessageBox.Show("Please insert an error");
            }

            if (txtData.Text.Length > 0)
            {
                server = comboBox1.Text; database = comboBox2.Text; KD = txtData.Text;

                //DATABASE CONNECTION (timeout 30seconds)
                connection.ConnectionString = "Data Source=" + server + "; Database=" + database + "; Integrated Security=True; Connect Timeout=30";

                //connection.ChangeDatabase("AnotherDatabase");
                command.Connection = connection;

                this.Result = this.ProcessData(this.command.CommandText);

                try
                {
                    connection.Open();
                    richTextBox1.Text = "Database Open";

                    reader = command.ExecuteReader();

                    txtResult.Clear();
                    richTextBox2.Clear();
                    listBox1.Items.Clear();


                    DataTable dataTable = new DataTable();
                    dataTable.Columns.Add("Message");
                    dataTable.Columns.Add("Stacktrace");


                    while (reader.Read())
                    {

                        //Load DataGridView1 with Data from Database
                        DataRow row = dataTable.NewRow();
                        row["Message"] = reader["Message"].ToString();
                        row["StackTrace"] = reader["StackTrace"].ToString();
                        dataTable.Rows.Add(row);
                        dataGridView1.DataSource = dataTable;

                        //Load data into reader from database
                        string message = reader["Message"].ToString();
                        string stacktrace = reader["StackTrace"].ToString();                       
                        
                        //Pass data from reader to textbox. 
                        txtResult.Text = String.Format("{0}", message);
                        richTextBox2.Text = String.Format("{0}", stacktrace);
           

                    }


                    int counter = listBox1.Items.Count;                  
                    counttxt.Text = ("" + counter);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
                finally
                {
                    connection.Close();
                    richTextBox1.Text = "Database Closed Sucessfully";
                }
            }
        }


Logic.cs

namespace connectionstring
{
    class Logic
    {

        SqlCommand command = new SqlCommand();


        public string ProcessData(string data)
        {

            command.CommandText = ("select DISTINCT Message, StackTrace from ErrorLog e " +
              "join ErrorIdentifier ei on ei.ErrorId = e.ErrorId " +
                 "left join KnownDefects kd1 on ei.HashValue = kd1.HashValue where ei.HashValue = " + data + "");

            return command.CommandText;
        }
    }
}

This post has been edited by Gadge: 24 September 2011 - 03:38 AM

Was This Post Helpful? 0
  • +
  • -

#11 Gadge  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 34
  • Joined: 08-April 09

Re: How do I reference the objects / variables in a form?

Posted 25 September 2011 - 03:18 AM

For anyone thatís interested I did manage to solve this issue, I was doing something silly this was resolved by:
I corrected this by changing:

this.Result = this.ProcessData(this.command.CommandText);

to
this.Result = this.ProcessData(this.command.CommandText + Data);


I do now however have an issue in which the string "command.commandText" is storing every entered string and passing it to my SQL statement so in the debugger its looks like:
"select DISTINCT Message, StackTrace, from ErrorLog e join ErrorIdentifier ei on ei.ErrorId = e.ErrorId left join KnownDefects kd1 on ei.HashValue = kd1.HashValue where ei.HashValue = 10 12"
10 and 12 had been entered separately so it will cause an error when trying to access my database since it cannot find the record. To get around this I have done:

command.CommandText = "";
this.Result = this.ProcessData(this.command.CommandText + Data);



Which Iím unsure would be the correct way of dealing with this? I think I should be putting some kind of clear statement within the class itself?
Iím trying to write decent code rather than pick up bad habitís so feel free to rip my program to shreds if you guys have better ideas.
Was This Post Helpful? 0
  • +
  • -

#12 CodingSup3rnatur@l-360  Icon User is online

  • D.I.C Addict
  • member icon

Reputation: 991
  • View blog
  • Posts: 971
  • Joined: 30-September 10

Re: How do I reference the objects / variables in a form?

Posted 25 September 2011 - 03:47 AM

Why not use the numeric up down control instead of a text box to allow the users to enter the number. That way, you can be sure that what they enter is a single, valid number :)

Further, in your SQL statement, do not build the SQL string using data input by the user by concatenation, as it potentially makes your program a prime candidate for SQL injection attacks. Use parameters whenever you have data input from the user that needs to go in a SQL statement, something like so:

using (SqlCommand command = new SqlCommand("select DISTINCT Message, StackTrace from ErrorLog e " +
              "join ErrorIdentifier ei on ei.ErrorId = e.ErrorId " +
                 "left join KnownDefects kd1 on ei.HashValue = kd1.HashValue where ei.HashValue = @hashValue", connection)) {
       command.Parameters.AddWithValue("@hashValue", data);
}




Also, looking through your code, a few things are confusing me slightly.

Why are you passing the command text to the ProcessData() method, especially when it is just an empty string?

Also, you create a SqlCommand object in your Logic class, add command text to it, then just return the command text. What purpose is that SqlCommand object serving in that class?

Why are you assigning the command text to the .Result property. Should the .Result property not contain the result of the query, rather than the SQL query itself?

A big problem is still that you are putting everything in the Form class. You are mixing UI code with logic and data access. You need to separate all logic from the UI. Yes you have a separate class, but you aren't really using it for anything, are you? :) Your just building the SQL query in it, and returning it. Remember, the UI should only really be concerned with updating itself. It shouldn't know where the data is coming from, or anything about how the data is gathered.

Also, please note that my member names in my example (Logic, ProcessData() etc) were just generic names, as it was just a generic example. You don't have to (and definitely shouldn't) stick to the template religiously. You need to change the template to fit your application, starting by giving your methods and classes meaningful names that actually reflect what they do :)

EDIT: Also, remember to dispose of all your disposable objects, like the SqlCommmand object above (that's why I put it in a using block, to ensure its Dispose() method is called automatically when we are done with it). In the case of SqlCommmand, it won't have any effect at the moment, but you don't know what Microsoft will do in the future. If it has a Dispose() method, you should try and call it if possible :)

This post has been edited by CodingSup3rnatur@l-360: 27 September 2011 - 12:50 AM

Was This Post Helpful? 1
  • +
  • -

Page 1 of 1