This question already has answers here:
Why is the control inaccessible due to its protection level?
(4 answers)
Closed 5 years ago.
In my project, I'm dynamically generating a lot of elements on a form, like buttons, picture boxes etc.
To separate the code, I'll be making new classes. I've made an instance of form1 in my new class, but all the elements are inaccessible -- why is this?
Edit: below is the relevant code. I'm trying to create buttons in CreateParty, but when I reference an element in form1 (in this case gameScrollBar), I get an error
Inaccesible due to its protection level
My code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
CreateParty createparty = new CreateParty(this);
generateIcons();
}
}
public class CreateParty
{
private Form1 mainForm;
public CreateParty(Form1 form1)
{
mainForm = form1;
testVoid();
}
public void testVoid()
{
Button NAButton = new Button();
NAButton.Height = 100;
NAButton.Width = 100;
NAButton.Location = new Point(190, 100);
NAButton.Text = "NA";
mainForm.gameScrollBar.Controls.Add(NAButton);
}
}
Any insight would be greatly appreciated.
You have declared the Form1 variable in your CreateParty class as private. Update your code to reflect:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
CreateParty createparty = new CreateParty(this);
generateIcons();
}
public class CreateParty
{
public Form1 mainForm; //This line was updated
public CreateParty(Form1 form1)
{
mainForm = form1;
testVoid();
}
public void testVoid()
{
Button NAButton = new Button();
NAButton.Height = 100;
NAButton.Width = 100;
NAButton.Location = new Point(190, 100);
NAButton.Text = "NA";
mainForm.gameScrollBar.Controls.Add(NAButton);
}
Related
I have Form1 where I want to use the list of objects listaPacienti I created in Form2 but it doesn't work.
Pacient is the class used to generate objects.
Here is Form1's beginning:
public partial class Form1 : Form
{
Form2 formPacienti = new Form2();
List<Pacient> listaPacienti = new List<Pacient>();
public Form1()
{
InitializeComponent();
}
And here is the beginning of Form2 where I created the list listaPacienti I want to pass to Form1:
public partial class Form2 : Form
{
List<Pacient>listaPacienti=new List<Pacient>();
Pacient p1 = new Pacient(0, "Pacient1", 0, 200);
Pacient p2 = new Pacient(1, "Pacienct2", 0, 100);
Form1 formMedici = new Form1(listaPacienti);
public Form2()
{
InitializeComponent();
listaPacienti.Add(p1);
listaPacienti.Add(p2);
}
What's wrong because I searched here before and that's how it is recommended to be done and if I wrote something wrong I don't know what it is because in Form2, the parameter "listaPacienti" from the following line
Form1 formMedici = new Form1(listaPacienti);
shows me this message: "A field initializer cannot reference the non-static field, method or property "Form2.listaPacienti".
Thank you
There are several things wrong here actually. The error itself is telling you that you can't use a class member when initializing a class member. You're trying to use listaPacienti to initialize formMedici. But you could initialize it in the constructor. Something like this:
List<Pacient> listaPacienti = new List<Pacient>();
Pacient p1 = new Pacient(0, "Pacient1", 0, 200);
Pacient p2 = new Pacient(1, "Pacienct2", 0, 100);
Form1 formMedici;
public Form2()
{
InitializeComponent();
listaPacienti.Add(p1);
listaPacienti.Add(p2);
formMedici = new Form1(listaPacienti);
}
However, your Form1 constructor also needs to accept that parameter. So you either need to modify the existing Form1 constructor or add a new one:
public Form1(List<Pacient> listaPacienti)
{
InitializeComponent();
// do something with listaPacienti?
}
However, it's not really clear why you're even doing this. You create an instance of Form2 in Form1:
Form2 formPacienti = new Form2();
Then you create an instance of Form1 in Form2:
Form1 formMedici = new Form1(listaPacienti);
This is an infinite recursion waiting to happen. Do you really want Form2 to create a new instance of Form1? Or do you want to use the existing instance of Form1? If the latter, then remove the references to Form1 entirely from Form2.
There are a variety of ways to accomplish the overall goal of what you're trying to do, and which one is ideal depends on more than what's presented here. But the simplest approach given the information present is probably to just make listaPacienti accessible from outside of Form2:
public List<Pacient> ListaPacienti { get; set; }
Pacient p1 = new Pacient(0, "Pacient1", 0, 200);
Pacient p2 = new Pacient(1, "Pacienct2", 0, 100);
public Form2()
{
InitializeComponent();
ListaPacienti = new List<Pacient>()
ListaPacienti.Add(p1);
ListaPacienti.Add(p2);
}
Now that listaPacienti is a public property, any code which has a reference to an instance of Form2 can access that property:
Form2 formPacienti = new Form2();
// Do other things with formPacienti?
// Either way, here you can access formPacienti.ListaPacienti
You need to add one more constructor to form one like this.
public Form1(List<Pacient> list)
{
this.listaPacienti=list;
InitializeComponent();
}
After that you can go with this code as you are going.
Form1 formMedici = new Form1(listaPacienti);
Move the instantiation of Form1 and listaPacienti into the constructor. This existing answer provides a good description of why you are getting this error - A field initializer cannot reference the nonstatic field, method, or property.
public partial class Form2 : Form
{
List<Pacient>listaPacienti;
Pacient p1 = new Pacient(0, "Pacient1", 0, 200);
Pacient p2 = new Pacient(1, "Pacienct2", 0, 100);
Form1 formMedici;
public Form2()
{
listaPacienti=new List<Pacient>();
formMedici = new Form1(listaPacienti);
InitializeComponent();
listaPacienti.Add(p1);
listaPacienti.Add(p2);
}
}
You can do the following
Sender Form:
private void btnIniciar_Click(object sender, EventArgs e)
{
this.Hide();
Main newMain = new Main(this.lsProcesos);
newMain.ShowDialog();
this.Show();
}
Receiver Form:
public partial class Main : Form
{
List<Proceso> lsProcesos;
public Main(object sender)
{
InitializeComponent();
lsProcesos = (List<Proceso>)sender;
}
}
My intension is to create a dynamic textbox in Form1. I have a Class 'Form1' and a Class 'SplBox'. I have declared a dynamic textbox in class 'SplBox' & passed a string to it. All I want is to call this dynamic textbox in class 'Form1' & display it in Form1 main form. In my above code a new form is getting opened up & then in this new form the dynamic textbox is shown - which I do not want
namespace TxtClassRun
{
public partial class Form1 : Form
{
SplBox s1 = new SplBox();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// show the dynamic text box in Form1
s1.settxtbox();
s1.Show(); // opening another window. I want it to be in "Form1"
}
}
//New Class
public partial class SplBox : Form
{
//Global declarations
TextBox t2 = new TextBox();
public void settxtbox()
{
t2.Text = "Hello World";
Controls.Add(t2);
}
}
}
Try this,
public partial class SplBox : Form
{
//Global declarations
TextBox t2 = new TextBox();
private Form TempOwnerForm;
public SplBox(Form TempOwnerForm) {
this.TempOwnerForm = TempOwnerForm;
}
public Form OwnerForm { get { return TempOwnerForm; } set { this.TempOwnerForm = value; } }
public void settxtbox()
{
t2.Text = "Hello World";
TempOwnerForm.Controls.Add(t2);
}
}
Hope helps,
I need to make windows forms program, that:
a) shows 2 forms with one textbox and one button each
b) when you press the button on one form, program copies text from that form to second form
c) when you press the button on the second form, program copies text from that form to first form
I've tried several different aproaches and got bogged down in encapsulation problems, since both forms has to be in separate instances, right? I've managed to make it work, so it creates new instance of form with new text in textbox every time you click, but after several steps I ended up with screen full of new windows and I need it to show only 2 windows through whole runtime.
Create the windows in your Main method, but don't show them immediately, then access them through the static properties:
public static class Program {
public static Form1 Form1 { get; private set; }
public static Form2 Form2 { get; private set; }
public static Int32 Main(String[] args) {
using( Program.Form1 = new Form1() )
using( Program.Form2 = new Form2() ) {
Application.Run( Program.Form1 ); // Form1's `Load` method would then show `Form2`
}
Program.Form1 = Program.Form2 = null;
return 0;
}
}
Form1 (is responsible for showing Form2 because Application.Run only shows a single form itself):
public class Form1 : Form {
protected override void OnLoad(...) {
Program.Form2.Show();
}
private void Button1_Click(...) {
Program.Form2.TextBox1.Text = this.textBox1.Text;
}
}
Form2 (you need to expose its TextBox via a public property):
public class Form2 : Form {
public TextBox TextBox1 { get { return this.textBox1; } }
}
Here's an example that shows how to pass a reference to the first form, into the second form using its Constructor. That reference is stored at class level so it can be used later. The exact same code/form is being used for both instances:
public partial class Form1 : Form
{
private Form1 target = null;
public Form1()
{
InitializeComponent();
this.Text = "Instance #1";
this.target = new Form1(this);
this.target.Text = "Instance #2";
this.target.Show();
}
public Form1(Form1 target)
{
InitializeComponent();
this.target = target;
}
private void button1_Click(object sender, EventArgs e)
{
if (this.target == null || this.target.IsDisposed)
{
this.target = new Form1(this);
this.target.Show();
}
this.target.textBox1.Text = this.textBox1.Text;
}
}
got bogged down in encapsulation problems, since both forms has to be in separate instances, right?
"encapsulation" immediately made me think of nested classes. The quintessential use case is for a class that is not/should not be used anywhere except in the containing class.
The idea is to allow clients to instantiate Form1 but have no access to Form2 or any of its members. If you need to expose anything from Form2 I suggest you write Form1 properties so that the client sees everything coming from Form1 only.
public class Form1 : Form {
protected Form Sibling { get; set; }
public Form1() {
Sibling = new Form2(this);
}
protected override void OnLoad(...) {
Sibling.Show();
}
private void Button1_Click(...) {
Sibling.TextBox1.Text = this.textBox1.Text;
}
protected class Form2 : Form {
protected Form Sibling { get; set; }
public Form1 ( Form mySibling ) {
Sibling = mySibling;
}
private void Button1_Click(...) {
Sibling.TextBox1.Text = this.textBox1.Text;
}
} // Form2
} // Form1
I have a textbox7 created in form1, but I want to access it in another form, form 2 so I changed its modifiers to public
When I get on form2 i want it to perform the following
Form1.textBox7.ReadOnly = true;
but I get the following error
Error 1 An object reference is required for the non-static field,
method, or property
'WindowsFormsApplication1.Form1.textBox7' C:\Users\Admin\Google
Drive\AdminhomeGD\ztese\zprograma\WindowsFormsApplication1\WindowsFormsApplication1\formOpConfig.cs 73 46 WindowsFormsApplication1
i have no idea what's wrong
Edit:
I'm trying to use the following, on form1 (named Form1):
public Boolean gammamanual
{
get { return textBox7.ReadOnly; }
set { textBox7.ReadOnly = value; }
}
while on form2 (named formOpConfig):
namespace WindowsFormsApplication1
{
public partial class formOpConfig : Form
{
public formOpConfig(Form1 opener)
{
// this is a constructor
this.Opener = opener;
}
private Form1 Opener { get; set; }
public formOpConfig() { // initialization and stuff }
private void buttonExit_Click (object sender, EventArgs e)
{
if (checkBox3.Checked == true) { this.textBox7.gammamanual = false; }
else { this.textBox7.gammamanual = true; }
this.Hide();
}
I want it so that when the checkbox3 is checked and the form2 exited, the textBox7 will be editable manualy.
Edit:2 the problem was that form2 was started from form1, also, i had 2 different constructors in form2 (formOpConfig). the solution was adapting the main constructor using
private Form1 Opener { get; set; }
public formOpConfig(Form1 opener)
{
this.Opener = opener;
InitializeComponent(); //Stuff
}
meanwhile i was able to start formOpConfig from the Form1 using
formOpConfig painelconfig = new formOpConfig(this);
painelconfig.ShowDialog();
You cannot access an instance variable via class name, that works only if it's static. So you need an instance of Form1 to access a property/field of it. You could for example pass it via constructor from Form1 to Form2(if Form1 instantiates Form2) or use a property/method.
But instead of exposing the complete control i would only provide what is necessary, that's called Encapsulation. You could expose a public property with a meaningful name that describes the purpose of textBox7(change also this name). Presuming it's purpose is to show a username the property could be UserName:
public partial class Form1 : Form
{
public string UserName
{
get{return TxtUserName.Text;}
set{ TxtUserName.Text = value;}
}
// ...
}
Since you want to get/set the ReadOnly property of the TextBox you could provide another property:
public bool UserNameEditable
{
get{ return !TxtUserName.ReadOnly; }
set{ TxtUserName.ReadOnly = !value; }
}
Now you are able to get/set it from another Form if you have an instance of Form1:
public partial class Form2 : Form
{
public Form2(Form1 opener)
{
// this is a constructor
this.Opener = opener;
}
private Form1 Opener { get; set; }
private void SomeMethod()
{
this.Opener.UserName = "Tim";
this.Opener.UserNameEditable = false;
}
// ...
}
You need to pass the Form1 instance to the constructor of Form2 when you instantiate it. Another approach is to make the property Opener public and use that which suffers the disadvantage that you cannot be sure that it was set.
Another approach is using LINQ and Application.OpenForms which is elegant but error-prone:
var form1 = Application.OpenForms.OfType<Form1>().FirstOrDefault();
form1.UserName = "Tim";
Side-note: Form1 and Form2 are also crying for more meaningful names.
In a form, the controls are created with a private access modifier (see the designer code).
private System.Windows.Forms.TextBox
Therefore, these controls are not accessible from another form. What you should do is create a public or internal property on your form.
public TextBox TextBox7 { get { return textBox7; } }
Once you created an instance of Form1 in (an instance of) Form2, you can access this property.
Form1 frm = new Form1();
frm.TextBox7.ReadOnly = true;
You need to create form1 instance and make a public property to set the control within form1.
public partial class Form2: Form
{
private Form1 objForm1;
public Form2(Form1 frm)
{
InitializeComponent();
//get other form
this.objForm1= frm;
//call here public property of form1 which set controls properties within form1
this.objForm1.SetReadOnly = true;
}
}
Form1
public partial class Form1 : Form
{
//setter Property
public bool SetReadOnly
{
set{ this.TextBox7.ReadOnly= value;}
get{ return this.TextBox7.ReadOnly;}
}
//Form1 Constructor
public Form1()
{
InitializeComponent();
}
//Form1 Load
private void Form1_Load(object sender, EventArgs e)
{
Form2 frm = new Form2(this);
frm.Show();
}
}
This is my form 2, this is where the checkboxes are.
My operator in here which is on the middle, has a random character generator, which my code is this :
char[] select = new char[] { '+', '-', '/', '%', '*' };
var rand = new Random();
char num = select[rand.Next(5)];
lbloperator.Text = Convert.ToString(num);
If the only check is addition, my form 1 will only perform addition, or if add,subtract, my form 1 will only perform add and subtract. Please help me with this! :(
FORM1
There is tow ways to do that:
1- first way is define public property in form2 that can tell form1 the status of checkBox1:
Form2:
public bool MyCheckBoxStatus
{
get {return checkBox1.Checked;}
}
Form 1 (For Example):
Form2 frm = new Form2;
frm.ShowDialog();
if (frm.MyCheckBoxStatus)
{
//Do something...
}
2- The other way: if you are using Windows Forms Application then all your controls have a property named Modifiers change its value to public and write this code in Form1:
Form2 frm = new Form2;
frm.ShowDialog();
if (frm.checkBox1.Checked)
{
//Do something...
}
Try this:
public partial class Form2: Form
{
public string checkBoxSelected = "";
}
public partial class Form1 : Form
{
private void MakeResult()
{
Form2 result = new Form2();
result.checkBoxSelected = "+";
result.Show();
}
}
I'm not too sure exactly what you are asking, but it sounds like you are trying to pass some data between forms.
In Form2, you can add a public property that reads your label
public string TheOperator {
get { return lblOperator.Text; }
}
Then from Form1, you can create a new instance of form2 and then reference the Property when needed.
Form2 fm = new Form2();
fm.Show();
string theOp = fm.TheOperator;
//////////
In response to your edit:
You can add this to Form1, exposing the operator variable there:
public string MyOperator {
get { return lblOperator.Text; }
set {
lblOperator.text = value;
//You can perform any updates to
//your calculations here, or call
//another method to do so
}
}
private void OpenForm2()
{
Form2 frm2 = new Form2(this);
frm2.Show();
}
Then inside of Form2, you pass a reference to Form1 so that you can access the public property:
private Form1 frm;
public New(Form1 _frm)
{
frm = _frm;
}
private void UpdateOperator()
{
//call this method, calculating your operator and then
//set the operator on the first form (variable frm) to
//What you need it to do
frm.MyOperator = lblOperator.Text;
}