To make my question as short as possible, this is my code. I wrote down the error I got in it.
public partial class VH : Form
{
public VH()
{
InitializeComponent();
//I can reach the pictureBox1 from here, but that's not what I want.
}
public static List<PictureBox> listPB;
public static bool mV()
{
bool Test = true;
listPB = new List<PictureBox>();
listPB.Add(pictureBox1); // <--- ERROR: An object reference is required for the non-static field, method, or property '...pictureBox1'
return Test;
}
I understand that I have to make the PictureBox static or available in some way but I don't know how.
I guess that picturebox1 is a control on VH that you added in the designer.
Now to your code "static" means that the function, variable or whatever else can be marked as static is not bound to an instance of your class.
So at the moment the call VH.listPB or VH.mV() from another class would be absolutly valid and because of that you get your error.
picturebox1 is not static, it needs an instace of VH but mV() could be called without an underlying instace of VH.
public bool mV()
{
bool Test = true;
listPB = new List<PictureBox>();
listPB.Add(pictureBox1);
return Test;
}
Without the static the code is valid although not very useful.
Related
I'm currently developing a Windows Form Application that uses two forms. I have no problems linking between the two forms. My issue is accessing a variable in Form2 that was created in Form1. How do you make a variable accessible to multiple forms in the same project?. I honestly tried to look for an answer, but could not find anything. Any help would be appreciated.
Here is the code for Form1:
namespace HourlyAlarm1
{
public partial class AlarmToneSetter : Form
{
public bool halfHourSelected;
public AlarmToneSetter()
{
InitializeComponent();
}
private void okButton_Click(object sender, EventArgs e)
{
if(halfHourRadio.Checked)
{
halfHourSelected = true;
}
else
{
halfHourSelected = false;
}
Form1 f1 = new Form1();
f1.ShowDialog();
}
public bool getHalfHourSelect()
{
return halfHourSelected;
}
}
}
Here is the code for Form2:
namespace HourlyAlarm1
{
public partial class Form1 : Form
{
int min;
System.Media.SoundPlayer sp;
public Form1()
{
InitializeComponent();
}
private void playSound()
{
sp = new System.Media.SoundPlayer(HourlyAlarm1.Properties.Resources.chipfork);
sp.Load();
sp.Play();
}
private void timer1_Tick(object sender, EventArgs e)
{
TimeLabel.Text = DateTime.Now.ToLongTimeString();
min = DateTime.Now.Minute;
if(HourlyAlarm1.AlarmToneSetter.g)
if(min == 0)
{
playSound();
}
}
}
}
If you want a variable which is accessible to any form within the project, mark it as static. That way you don't need a specific instance of the class that it's in to be able to access it.
You can use the forms Tag property if you want to pass just one variable.
Form1 f1 = new Form1();
f1.Tag="some value";
f1.ShowDialog();
and then in form 2 access it via it's own Tag property. Since it is stored as an object you will have to convert it to whatever datatype your application requires.
Example for getting the value in the new form:
string value = this.Tag.ToString();
As the question currently stands, it looks like you're trying to edit the halfHourSelected field in your AlarmToneSetter class from the Form1 class. To do that, there are several options:
Since this field is already public you can simply edit it like this (form Form1):
HourlyAlarm1.AlarmToneSetter.halfHourSelected = true;
or, if you plan on using it several times, add
using HourlyAlarm1;
/**
* declare the namespace, the class, etc.
*/
AlarmToneSetter.halfHourSelected = true
(Edit: As mentioned by Jason, this can be rewritten to be a property and comply with the style guide) However, since you already wrote a Java-style getter for this field, you should rewrite it in C# style; changing the declaration to
public bool HalfHourSelected{get;set;};
which will add the getter and setter for the property automatically.
Now, if you want to make this field persistent (that is, the configuration value should be saved across multiple executions of the program) then you should consider adding it to the settings of your project, and reference it like this
HourlyAlarm1.Properties.Settings.Default.halfHourSelected = true;
HourlyAlarm1.Properties.Settings.Default.Save();
or, as always, if you're gonna access them several times,
using HourlyAlarm1.Properties;
/**
* declare the namespace, the class, etc.
*/
Settings.Default.halfHourSelected = true;
Settings.Default.Save();
Yes, this is my first time answering a question in SO. If you have any recommendations, let me know in the comments! I'll appreciate the feedback.
Pass them as parameter of constructor. This way is used to set once time at creating an instance of class
public Form1(int i, string s, object o){}
Create public get/set. This way is used to set multiple times, but their value will be different among instances of class.
public int Price { get; set;}
Form1 frm1 = new Form1();
frm1.Price = 123;
Create public static field. This way is used to set multiple times, and it is same among instance of class.
public static int Price = 0;
Form1.Price = 123;
First of all public fields are discouraged in .NET: you should use properties.
Your problem is that bool is a value type and you can't "bind" it between forms, you need a reference type.
public class ReferenceBoolean
{
public bool Value{get;set;}
}
public class Form1
{
protected ReferenceBoolean HalfHourSelectedReference{get;set;}
public bool HalfHourSelected
{
get{return this.HalfHourSelectedReference.Value;}
set{this.HalfHourSelectedReference.Value = value;}
}
public Form1()
{
this.HalfHourSelectedReference = new ReferenceBoolean();
}
}
public class Form2
{
protected ReferenceBoolean HalfHourSelectedReference{get;set;}
public bool HalfHourSelected
{
get{return this.HalfHourSelectedReference.Value;}
set{this.HalfHourSelectedReference.Value = value;}
}
public Form2(ReferenceBoolean halfHourSelected)
{
this.HalfHourSelectedReference = value;
}
}
Now this might look all fine and dandy but there is one thing I did not do, because I'm not sure if you need it, if you update this value and have it bound to the UI in your form the update will not be reflected in the form. To do that you must implement something like the IPropertyNotificationChange pattern, which works much better in WPF.
I am brand new to C# (I apologise if my question is noobish - I'm teaching myself, so it's a bumpy process). I am trying to develop a winform and since some of the methods are pretty long, I am trying to keep it in a couple classes. This is what I'm kind of hoping to achieve:
public partial class formMainForm : Form
{
public formMainForm()
{
InitializeComponent();
}
private void UpDown1_ValueChanged(object sender, EventArgs e)
{
longCalculations.LongMethod1();
}
}
public class longCalculations
{
private void LongMethod1()
{
// Arbitrarily long code goes here
}
}
I'm doing this in an attempt to keep the formMainForm class tidy and be able to split any calculations into manageable chunks. However, I'm encountering problems with using form controls (e.g. check boxes, numeric up-down controls, etc.) in my non-form classes.
If I leave them as is (e.g. CheckBox1) I get a the name does not exist in the current context error. I searched around and I found that it's because that box is defined in a different class. However, if I change it to formMainForm.CheckBox1, the error is now an object reference is required for the non-static field, method or property. Again, I looked around and it appears that that is due to the form initialization method not being static.
If I change public formMainForm() to static formMainForm(), the error now moves to InitializeComponent(); and I do not know where to go from here. I also tried making an instantiation of the formMainForm() method, but that didn't do anything (the code I attempted to use is below. I found it somewhere on this site as an answer to a similar problem).
private void formLoader(object sender, EventArgs e)
{
shadowrunMainForm runForm = new shadowrunMainForm();
runForm.Show();
}
How can I use the formcontrol names in other classes?
P.S. It is my first post here - I am super sorry if I have missed this question already being asked somewhere. I did search, but I didn't find what I was looking for.
EDIT
It seems I hadn't made myself clear - this was just an example of code and my problem is with the second class, not the first one. I have now simplified the code to:
public partial class formMainForm : Form
{
public formMainForm()
{
InitializeComponent();
}
}
public class longCalculations
{
private void LongMethod1()
{
List<CheckBox> listOfBoxes = new List<CheckBox>();
listOfBoxes.Add(CheckBox1);
// The code displays an "object reference is required for the non-static field, method or property" error at this stage. Changing the "CheckBox1" to formMainForm.CheckBox1 doesn't help
// Arbitrarily long code goes here
}
}
LongMethod1 works perfectly fine when placed in the formMainForm partial class. Moving it to the other form makes it unable to take data from those checkboxes.
I believe this line longCalculations.LongMethod1(); is throwing error cause you are trying to access a instance method as if it's a static method and as well it's defined as private method which won't be accessible outside the class. You need to create an instance of longCalculations class before accessing any of it's member or method(s) and mark the method public like
private void UpDown1_ValueChanged(object sender, EventArgs e)
{
longCalculations ln = new longCalculations();
ln.LongMethod1();
}
public class longCalculations
{
public void LongMethod1()
{
// Arbitrarily long code goes here
}
}
(OR) If you really want it to be a static method then define accordingly with static modifier like
public class longCalculations
{
public static void LongMethod1()
{
// Arbitrarily long code goes here
}
}
Now you can call it like the way you are trying
public static class longCalculations
{
public static void LongMethod1()
{
// Arbitrarily long code goes here
}
}
If you're going to make a call longCalculations.LongMethod1();, then you need to make your class static as such.
Or you leave it as not static method by calling
longCalculations lc = new longCalculations()
lc.LongMethod1();
As for accessing controls in separate classes, you can pass in the form and make the controls public which can be dangerous.
So on your Form.designer.cs, change any control you may have to public modifier. Then you would make a call like this...
private void UpDown1_ValueChanged(object sender, EventArgs e)
{
longCalculations.LongMethod1(this);
}
public void LongMethod1(Form1 form)
{
// Arbitrarily long code goes here
form.label1.Text = someString;
//more settings and whatnot
}
Or do something like this:
public class longCalculations
{
public string LongMethod1()
{
// Arbitrarily long code goes here
return myString;
}
}
longCalculations lc = new longCalculations()
string result = lc.LongMethod1();
this.label1.Text = result;
Ideally, your longCalculations class would not attempt to modify the form directly. Instead it would return an object that the form could use to update its controls.
If you need to access the form directly from the longCalculations class, first change the method to accept an instance of your form
public void LongMethod1(formMainForm myForm)
Then you can pass the form itself as a parameter
var calc = new longCalculations();
calc.LongMethod1(this);
In your other class, you need to have an instance of your formMainForm class:
var myForm = new formMainForm();
Then you can access its members like this:
myForm.CheckBox1.Checked = true;
I am a complete amateur at programming and am trying to learn proper code design. I`m trying to learn how to use accessors but can't seem to get it to run properly. This is what I am trying to run:
class Classy
{
public void changeLine(string change)
{
Form1 form1 = new Form1();
form1.Line = change;
}
}
public partial class Form1 : Form
{
string line = "";
public string Line
{
get
{
return line;
}
set
{
line = value;
}
}
private void button2_Click(object sender, EventArgs e)
{
line = "";
string change = "cake";
Classy classy = new Classy();
classy.changeLine(change);
MessageBox.Show(line);
}
When I click the button, it shows blank text. From what I understand these are the steps it take:
variable change with "cake" value is passed to classy's changeLine method.
changeLine method sets Form1 line to variable change with "cake" value.
MessageBox displays line variable of "cake" value.
Why does this not work?
This is happening because you are creating a new instance of Form on the changeLine method. This new instance is different from the one the event was fired, or the button was clicked.
In order to use the correct Form reference, you may pass the actual reference as an argument:
public void changeLine(Form1 form, string line) {
form.Line = line;
}
You would call this method (from the form) like this:
classy.changeLine(this, change);
this is the current Form1 instance, it is the one you want to modify. You don't want to create a new one.
Okay. You've got a Form1 object and the window it represents and controls is displayed on screen. You click a button and it invokes a method.
line = "";
This line is a private field which happens to be the backing field to the Line property. At this point accessing either the line field or the Line property will return "".
string change = "cake";
A string local to this method.
Classy classy = new Classy();
Okay, we've a new object of type Classy called classy.
classy.changeLine(change);
Let's look at what this call does:
Form1 form1 = new Form1();
You now have a different Form1 object. If you called form1.Show() you would now have two windows on the screen`.
form1.Line = change;
Sets the Line property (and hence the line field) of this new, different Form1.
We now return back to the calling method:
MessageBox.Show(line);
Shows the value of the line field of the original Form1 object.
To demonstrate a property being set from outside the class you could do something like:
class Classy
{
public void changeLine(Form1 form1, string change)
{
form1.Line = change;
}
}
public partial class Form1 : Form
{
string line = "";
public string Line
{
get
{
return line;
}
set
{
line = value;
}
}
private void button2_Click(object sender, EventArgs e)
{
string change = "cake";
Classy classy = new Classy();
classy.changeLine(this, change);
MessageBox.Show(line);
}
}
Here because the Form1 passes itself (this refers to the object of the method running) to classy its own Line property will now be used.
Alternatively:
class LineStorer
{
private string _line;
public string Line
{
get { return _line; }
set { _line = value; }
}
}
public partial class Form1 : Form
{
private void button2_Click(object sender, EventArgs e)
{
var storer = new LineStorer();
storer.Line = "cake";
MessageBox.Show(storer.Line);
}
}
Here the form is first setting and then getting a property in another object.
Note also that objects can use their own properties instead of the backing field:
public partial class Form1 : Form
{
private string _line;
public string Line
{
get { return _line; }
set { _line = value; }
}
private void button2_Click(object sender, EventArgs e)
{
Line = "cake";
MessageBox.Show(Line);
}
}
From the inside, so to speak, there's really not much difference whether one uses a field or a property, but using properties does have an advantage in that if some day you changed from this simpler property (read and write from and to a field and do nothing else) to one that is more complicated (common cases including validation checks on all setting, but you are far from limited to that) then you'd only have to change the one place where the property is defined rather than the, perhaps very many, places where it is used.
(It may seem like using Line is more work than just using line, because it does after all call into more code, and therefore using properties rather than fields would be a slight inefficiency that would add up over time. Luckily the jitter is smart enough to "inline" simple getters and setters when the code is run, so there is in fact no cost to them).
What you do is what you get. You want to show the value of line, but you never set it to another value before showing it. Whatever you do in these three lines of code has nothing to do with changing the value of line IN THIS PARTICULAR INSTANCE OF THE CLASS FORM1.
string change = "cake";//You declare and initialize a variable
Classy classy = new Classy();//You create an instance of class Classy
classy.changeLine(change);//You invoke a method in that class that has no clue of what is going on this side
Yes, it does set the value of line to "cake", but on ANOTHER OBJECT. But you could still get the behavior you need in at least two ways:
You could have an instance variable in the Classy class of type Form1 and have a constructor that would receive a Form1 object as a parameter. Then in your changeLine method, instead of creating a brand new Form1 object you could change the line of that particular instance variable, like this:
public class Classy{
private Form1 _form1;
public Classy(Form1 form1){
_form1=form1;
}
public void changeLine(string change){
_form1.Line=change;
}
}
You could change your changeMethod to accept an additional parameter of type Form1 and then pass it this when invoking it inside Form1
public void changeLine(string change,Form1 form1){
form1.line=change;
}
And on the Form1 side:
classy.changeLine("cake",this);
I have a grid class and a MainWindow class. Grid's class function needs to call MainWindow's function:
// function from grid class:
public Point functionFromGridClass()
{
Point variable = MainWindow.functionFromMainWindowClass(0, 0);
// ...
}
// function from MainWindow class:
public static Point functionFromMainWindowClass(int x, int y)
{
Vector2 mouse;
mouse.X = x;
mouse.Y = y + (ClientRectangle.Height - glview.Size.Height);
// ...
}
If I remove static keyword in functionFromMainWindowClass, then I can't call it from grid class. If I don't remove static keyword, then I can't use the MainWindow's class variables ClientRectangle and glview, I get a warning "An object reference is required for the non-static field, method, or property". I've never faced this problem, what should be the solution?
The grid class has to hold a reference of an instance of the MainWindow and probably provided to grid upon construction.
public class GridClass
{
private MainWindow window;
public GridClass( MainWindow Window)
{
window = Window;
}
public Point functionFromGridClass()
{
Point variable = window.functionFromMainWindowClass(0, 0);
}
}
I get a warning "An object reference is required for the non-static field, method, or property"
The warning tells you what to do: you need an instance in order to call instance methods.
So you could remove the static keyword from the method and then in your Grid class create an instance of MainWindow in order to be able to call the method:
var mainWindow = new MainWindow();
var result = mainWindow.functionFromMainWindowClass(5, 6);
It's hard to give specific advice without knowing exactly what is going on, but the general picture is that you need to somehow get the instance of the MainWindow class that you want to call the method on, either by passing it into Grid at construction or similar, or by getting it from some resource manager.
Static methods are called with reference of the className.
Call you Main window class function like this:
public Point functionFromGridClass()
{
MainWindowClass.functionFromMainWindowClass(val1, val2);
}
Updated to be more clear....
I have a main form, Form1, and an additional class, AslLib. Form1 contains a method that updates a dataGridView control it contains. A method in AslLib calls this method.
My problem is that the only way I can make AslLib call Form1's method is by creating an instance of Form1 in AslLib's calling method like so:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void updateDataGUI(int row, string url, string status, long time)
{
Console.WriteLine(status);
foreach (DataGridViewRow dgvr in dataGridView1.Rows) dgvr.Cells[0].Value = status;
}
}
static class AslLib
{
public static async void makeRequest(string url, int row )
{
string result;
Stopwatch sw = new Stopwatch(); sw.Start();
try
{
using (HttpClient client = new HttpClient())
{
HttpResponseMessage response = new HttpResponseMessage();
response = await client.GetAsync(url);
if (response.IsSuccessStatusCode)
{
result = ((int)response.StatusCode).ToString();
}
else
{
result = ((int)response.StatusCode).ToString();
}
}
}
catch (HttpRequestException hre)
{
result = "Server unreachable";
}
sw.Stop();
long time = sw.ElapsedTicks / (Stopwatch.Frequency / (1000L * 1000L));
_form.updateDataGUI(row, url, result, time);
}
}
I have tried passing parameters in both the constructor and the method, but because (i think) the makeRequest method is static, the compiler is giving errors:
AsyncURLChecker.AslLib._form: cannot declare instance members in a static class AsyncURLChecker
Static classes cannot have instance constructors AsyncURLChecker
The result of the above is that the Console.WriteLine(status); part of Form1's method correctly outputs status, but the dataGridView does not change.
My belief is that because I am creating a new instance of Form1, I am no longer referencing the original Form1 containing my dataGridView, rather an entirely new copy, so it is not changing.
Can anyone tell me how I might manipulate the original Form1's dataGridView from another class? My preferred method would be to call a Form1 method that updates dataGridView rather than directly accessing dataGridGiew from AslLib if possible.
You should pass reference to existing form instead of creating new one:
// on Form1
Class1 c1 = new Class1();
c1.DoSomething(this);
// Class1
public void DoSomething(Form1 form)
{
form.updateDataGUI(row, url, result, time);
}
Pass the form into the class constructor
private Form1 _form;
public Class1(Form1 form)
{
_form = form;
}
you now have access to the form from within your class.
You need to have the original created instance of the MainForm. Here is one way you can access it:
Application.OpenForms.OfType<MainForm>().First().updateDataGUI(row, url, result, time);
(Application.OpenForms contains all the open forms of the currently running application.)
But it is better to redesign your class structure in such a way that you can pass the reference of the MainForm object to the class. Another option is to hold the instance in a static property of the MainForm itself (if you are sure that only one instance exists at any time).
I think you can use this.
MainForm f = (MainForm)this.Owner;
f.updateDataGUI(row, url, result, time);