14
Answers

How to access a controll in another form

Lars Persson

Lars Persson

13y
1.5k
1
I have asked a similar question in the C# forum but seemed like a good idea to separate the issue and change forum. (Thanks Sam and Vulpes!)

If I want to access a control in another form from the current form or class, how do I do this?

How does it really work?

Form1.ListBox1 is clearly not enough.




Answers (14)
0
Vulpes

Vulpes

NA 98.3k 1.5m 13y
As I said in the previous thread, you need a reference to a form instance in order to access its controls.

Another way to do it (apart from Application.OpenForms) is to define a static property in the form itself which exposes such a reference. This only works if there's only ever a single instance of a particular form which is usually the case:

   public partial class Form1 : Form
   {
      internal static Form1 Me;

      public Form1() // constructor
      {
         InitializeComponent();
         Me = this;
      }

      // rest of code
   }

From another form or class in the same application, you can then get your reference as follows:

   Form1 f1 = Form1.Me;

There are (at least)  2 other ways (apart from using the Controls collection) to access  a control on a form:

1. Change the control's Modifiers property from private to either internal or public so it can then be seen by other forms or classes in the application. You can then do:

   ListBox lb = f1.listBox1;

2. Create an internal or public method (or a readonly property) on the form to expose the control to other forms or classes:

   internal ListBox GetListBox()
   {
       return this.listBox1;
   }

You can then do:

   ListBox lb = f1.GetListBox();



Accepted
0
Sam Hobbs

Sam Hobbs

NA 28.7k 1.3m 12y
I now about LINQ but I have not used it much. I am not aware of it having the ability to read and write data from and to disk. It can probably be used to execute methods that does the reads and writes but LINQ should not be considered to be for that purpose. LINQ is more for doing database stuff in memory only. LINQ is like SQL in some ways but they are very different; at least in syntax. In my opinion it is a shame that LINQ is so much different from SQL.
0
Lars Persson

Lars Persson

NA 108 0 12y
I do know about relationships among database tables but the program was made as excercise in OOP.

Have you used LINQ. As I understand it you can save the objects to a relational database using LINQ. 
0
Sam Hobbs

Sam Hobbs

NA 28.7k 1.3m 12y
There are many ways to save data. A plain text file like that is a simple format. Another format is XML. The ultimate format is database. I certainly consider database to be the best; it can even be the easiest to program since Microsoft (and other developers) have already done for us the details of the programming for databases. I do not know how much you know about relationships among database tables but it is the type of thing you are doing; if you do not use database tables then you are doing some of the details that a database will do for you automatically.

As a learning exercise, a text file such as this can be educational. There is so much to learn and I understand that we need to prioritize what to learn.
0
Lars Persson

Lars Persson

NA 108 0 12y
Thanks Sam!

A good explanation!

I think I said somewhere that I saved the objects or something but I only meant saving to a variabel. I was however saving to disc using streams in Java so it´s great that you showed me how.
0
Sam Hobbs

Sam Hobbs

NA 28.7k 1.3m 12y

Attachment 167218.zip

Ooops, I did not post the attachment. Here it is.
0
Sam Hobbs

Sam Hobbs

NA 28.7k 1.3m 12y
Note that I spent too much time trying to get the formatting of this post correct. The formatting is not perfect but I will not fix that.

As far as I know, you still have not specified how the data is saved. That however can affect how the data is processed by the program. I give you credit for asking specific questions. Many questions are quite general; asking how to write an entire program. My reply to many of them is that they need to ask specific questions. You are doing that so I need to give you credit for that. If I knew however how you are saving the data then that would help. The following is intended to show how to access data in anohter form. This is intended to be an object-oriented solution. This is not inended to be a complete program; it is primarily a sample of passing data to another form and getting data from the form.

In this sample, a CSV file of customers is read from and written to. That is done in the "Program" class which is in the Program.cs file. The Program class is static; it must be since it has the Main method which must be static. The class and the method must be static so that Windows can execute the program. So the Program clss in this sample has the following member:

 public static  BindingList <Customer> Customers = new  BindingList <Customer>();



Which is a list of Customer objects. I use a BindingList but a List would probably be the same for your purposes. The Customer class is:

public  class  Customer 

{

public  string  id { get ; set ; }

public  string  name { get ; set ; }

}



Of course your Customer class has more members but this is just a sample. The data is read (using GetCustomers()) before the main form is shown and then when the main form is closed the data is written (using PutCustomers()). So the Main has the following:

Application .EnableVisualStyles();

Application .SetCompatibleTextRenderingDefault(false );

GetCustomers();

Application .Run(new  Form1 ());

PutCustomers();



And the following are the GetCustomers() and PutCustomers():


private  static  void  GetCustomers()

{

char [] delimiters = {  ,   };

String [] itemarray;

Customer  c;

FileInfo  fi = new  FileInfo (Filename);

if  (!fi.Exists)

return ;

using  (StreamReader  file = new  StreamReader (Filename))

{

while  (!file.EndOfStream)

{

itemarray = file.ReadLine().Split(delimiters, 2);

if  (itemarray.Length == 2)

{

c = new  Customer ();

Customers.Add(c);

c.id = itemarray[0];

c.name = itemarray[1];

}

}

}

}

 

private  static  void  PutCustomers()

{

using  (StreamWriter  file = new  StreamWriter (Filename))

{

foreach  (Customer  c in  Customers)

{

file.WriteLine(c.id + +c.name);

}

}

}


However note that the code shown above is incomplete; the tool I use to format source code is not perfect. So the following are two lines that are shown without the formatting tool that are the correct version of the code above.           

char[] delimiters = { '\t', ' ' };

file.WriteLine(c.id +'\t'+c.name);

Okay so that is how the program reads and writes the data. The main form of the program has a DataGridView and a menu bar. The form has a BindingSource as a member; it is:


BindingSource  bs = new  BindingSource ();

The Customers list is bound to the DataGridView in the form load event using:


bs.DataSource = Program .Customers;

dataGridView1.DataSource = bs;


    
That is all that is needed to bind the data to the control. You can download the attached project to see how it works.


Note that a DataGridView allows rows to be added and edited in it, so we do not need a second form. If however you do not want to use a DataGridView then this sample is useful for showing how to use a second form to edit the data; you do not have to use a DataGridView in your program. The main form also has a menu bar with commands to add or edit customers using a second form. The following code will use the second form to add a record:
 

Customer  c = new  Customer ();

Form2  f = new  Form2 (c);

DialogResult  dr = f.ShowDialog();

if  (dr != DialogResult .OK)

return ;

Program .Customers.Add(c);

Program .Customers.ResetBindings();


In this sample, a row in the DataGridView needs to be selected for the edit to happen. The following will edit the selected row:


if  (dataGridView1.SelectedRows.Count != 1)

{

MessageBox .Show("Nothing selected" );

return ;

}

Customer  c = dataGridView1.SelectedRows[0].DataBoundItem as  Customer ;

Form2  f = new  Form2 (c);

DialogResult  dr = f.ShowDialog();

if  (dr != DialogResult .OK)

return ;

Program .Customers.ResetBindings();



       


The important thing here is that the Form2 object is being created with a constructor that takes a Customer object as a parameter. That is the important thing and it is very fundamental to object-oriented programming and languages such as C#, Java and C++. There is nothing exotic or advanced about doing that. The Form2 class has a Customer object as a member; as in:           

Customer c = null;

The Form2 class has a constructor that takes a Customer object as a parameter; the following is the complete constructor:



public  Form2(Customer  c)

{

InitializeComponent();

this .c = c;

textBoxId.Text = c.id;

textBoxName.Text = c.name;

}


The Constructor also sets the textboxes to the values of the Customer object. Then the Okay button click event does the following:



DialogResult = DialogResult .OK;

c.id = textBoxId.Text;

c.name = textBoxName.Text;

Close();


The Cancel button click event does the following:


DialogResult = DialogResult .OK;

c.id = textBoxId.Text;

c.name = textBoxName.Text;

Close();


The relevant portion of code is very simple. We simply pass an object to the constructor and the form uses just one object. The object (Customer) can have many more properties and regardless of how many properties it has, the constructor only needs one parameter.


0
Lars Persson

Lars Persson

NA 108 0 13y
Ok, here comes some clarification:

I´ve making a simple system for a library.

You can create books as objects and customers as objects. Both of these are added to a List-controll.

You can then search for books, see what books there are and have a list of the customers.

It is an old project I made in Java that I´m trying to convert to C#.

Since there are a lot of information in the interface I want the list of customers to be a popup so it doesn´t take up space.


0
theLizard

theLizard

NA 5.1k 282.2k 13y
An alternative without needing to change modifiers of the controls you want access to is.

a) create a public function in the form you want other forms to access its controls.

b) create a second constructor in the form you want to access another forms controls with 1 parameter, the form you want to access its controls.


namespace WindowsFormsApplication1
{
   
    public partial class frmMain : Form
    {
        public frmMain()
        {
            InitializeComponent();

        Form2 f = new Form2(this);  //create the second form parsing this as its parameter.
          f.Show();
         
        }
        //----------------------------------------------------------------------
        //nothing out of the ordinary here, simply a way to return the form control to the calling form

        public Control getControl(string name)
          {
          Control ctrl = null;
          for (int i = 0; i < Controls.Count; i++)
            {
            if (Controls[i].Name == name)
              {
              ctrl = Controls[i];
              break;
              }
            }
          return (ctrl);
          }
 
       //----------------------------------------------------------------------
}

Then all you have to do in any other form that needs access to controls of other form is to call the getControl(...) method

eg  ((TextBox)frm.getControl("TextBox1")).Text = "Hello World";

or TextBox te = (TextBox)frm.getControl("TextBox1");  //to access all the properties of TextBox1
     eg  te.Focus(), te.BackColor = Color.Blue;

namespace WindowsFormsApplication1
{
    public partial class Form2 : Form
    {
      frmMain frm;   //form scope

        public Form2(frmMain f)
        {
            InitializeComponent();
            frm = f;                         //assign f to frm;
        }
        public Form2()
        {
          InitializeComponent();
        }
        private void Form2_Load(object sender, EventArgs e)
        {
        }
        private void button1_Click(object sender, EventArgs e)
        {
          ((TextBox)frm.getControl("e2")).Text = "Hello World in TextBox of first form";

        or it could be a combo box, list box, tree view

        ((ComboBox)frm.getControl("cbItems")).Items.Add("Hello World added to ComboBox on first form");

        }
    }
}





0
Sam Hobbs

Sam Hobbs

NA 28.7k 1.3m 13y
I prefer to answer questions after getting clarification. Vulpes tends to try to answer without getting clarification. I think we often need to get clarification before we are able to suggest the most approriate solution. Unfortunately deverlopers usually don't want to provide clarificaton after they have something that works.

I will post a suggeston later today that you can consider for the future at least.
0
Lars Persson

Lars Persson

NA 108 0 13y
Well, I really want to learn "the right way" to do it, if there is one.

I´ve got it working now anyway.

What I´m doing is open Form2 using a button in Form1. I have a List controll containing objects that I want to show in a separate window to keep a cleaner interface.

Again, thanks to both!
0
Sam Hobbs

Sam Hobbs

NA 28.7k 1.3m 13y
As I indicated in the other thread, instead of Form1.ListBox1 a better methodology is to create a method or property in Form1 that does to ListBox1 whatever needs to be done.

As for having a reference to a form from another form, it depends on which form creates which form. It might also depend on whether a form is shown modally (with ShowDialog) or modelessly (using Show). So what is the relation of Form1 to the ohter form? Does Form1 create the other form or is it crated by the other form?

I prefer to use more object-oriented solutions but since that depends on what the objects are the answer depends on more information. We need clarification.
0
Vulpes

Vulpes

NA 98.3k 1.5m 13y
You'll find that all the properties of a control which are listed in the Properties Box are public anyway, so there's nothing to do there.

So, if you wanted to access the listbox's DataSource property you could do so with:

   object source = lb.DataSource;

However, you'd need to cast 'source' to its actual type (perhaps a DataTable or List<string>) before you could do much with it.
0
Lars Persson

Lars Persson

NA 108 0 13y
Great, think I´m getting the hang of it.

Some questions:

Can I set all the properties to public of a controll or do I have to choose Source for instance?

In the second example, can I then write lb.Source?