It seems like it should be simple enough, but im having trouble wrapping my brain around it. Normally you would declare an object in one of a couple ways
ClassName a;
a = new ClassName();
or
ClassName a = new ClassName();
etc...
but since you're explicitly declaring these at compile time i get confused when Im supposed to code this to happen at runtime. What I want to do is have a new instance of the Class instantiated when a button is clicked. But what I'm not grasping here is how is the object name going to be named if this is happening on button click?
Even worse, Objects don't have a Name at all.
The variable you are naimg is the reference to the object.
It matters what you decide the object will belong to:
void ButtonClick_H1(...)
{
ClassName a; //local variable
a = new ClassName(); // object belongs to this method
}
private ClassName anObject; // class field
void ButtonClick_H2(...)
{
anObject = new ClassName(); // object belongs to 'this' Form
}
public partial class Form1
{
Classname myClass;
public void Button1_Click(...)
{
myClass = new Classname();
}
}
?
Well, you create the object using the code you showed above, and that will be the new instance of your Class. If you declared a inside the scope of the method it will cease to exist after the method (unless there are external references to it), but if you declare it outside the method as a class variable it will stay until the class is destroyed.
In exactly the same way as you would usually name an object.
You need to hook into the button's Click event:
this.Button.Click += new RoutedEventHandler(Button_Click);
Then use something like
private void Button_Click(object sender, RoutedEventArgs e)
{
ClassName a = new ClassName();
}
Related
So my problem is as follows:
I am passing an object called Items of class MyClass into a new instance of MyWindow in WPF. And I am passing by value, not by reference. Then I bind certain controls (textboxes, comboboxes, etc.) of MyWindow to the properties of a new field called ItemsReplicate of MyClass that belongs to MyWindow and is made equal to Items. However, when I make changes to any control in MyWindow, Items's properties get overwritten too for some reason. Is this normal? Or am I missing out on something?
Here's the code description:
var passThis = (MyClass)myItem;
MyWindow wnd = new MyWindow(passThis);
public partial class MyWindow : Window
{
public MyWindow (MyClass _item)
{
InitializeComponent();
innerItem = _item;
this.DataContext = innerItem ;
}
private MyClass innerItem;
}
So in the end of this procedure, any changes made via binding affects both myItem and innerItem
Many thanks.
PS: Binding mode: Two-way
Edited after comment.
Default parameter passing for classes is per reference, even without the "ref" keyword, which only makes changes to the reference of the object itself visible "on the outside".
MyClass c = new MyClass();
MyMethod(c);
MyRefMethod(ref c);
public void MyMethod(MyClass innerc)
{
innerc = new MyClass(); //stays local, c is still its old reference
}
public void MyRefMethod(ref MyClass innerc)
{
innerc = new MyClass(); //c becomes a new reference to the local innerc
}
As in your case: You pass a copy of the reference to MyClass as '_item'. You then store that reference-copy in 'innerItem' as well as in the DataContext. It is still only one Instance of MyClass with multiple reference-copies. Every copy of a reference just points to the same instance of the class.
When you modify the values of your public properties of MyClass with the binding in WPF, the values inside of your original instance of MyClass are getting an update.
In other words: This is normal behavior.
If you really want a deep copy of your Class, the easiest way is to serialize and desialize it.
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'm wondering as to why my private variable 'name' within my Events class won't change when I access the property from my Leisure class which inherits from Events. I need Leisure to use the properties to change it, and then in my form class, it should be able to read the value of 'name' from events. See below:
public partial class Form1 : Form //Main form class
{
private string eventType; //used for event type selection
private string formEventName; //used to store selected event name
private void itemSend_Click(object sender, EventArgs e)
{
//encapsulation
Events myEv = new Events();
string name=itemInput.Text;
myEv.myEvent(eventType, name);
formEventName = myEv.myName;
txtOutput.Text = "Event name is " + formEventName + "\r\n";
}
class Events:Form1
{
private string name; //private variable for event name
public string myName //used to change property value depending on what eveny type/ event name
{
get { return name; }
set { name = value; }
}
public void myEvent(string eventType, string eventName) //variable recieved from main form class
{
if (eventType == "Leisure")
{
Leisure myLes = new Leisure();
myLes.eventNames(eventName);
}
else
{
//test for other event types
}
}
class Leisure:Events
{
public void eventNames(string eventName)
{
//when adding new items add one with a capital and one without
myEventNames.Add("music");
myEventNames.Add("Music");
if (myEventNames.Contains(eventName))
{
myName = eventName;
}
else
{
MessageBox.Show("item not found, please try again"); //error message
}
}
}
It seems wrong that Events inherits from Form1.
When you say new Events(), you get a new object, unrelated to the existing form, and any changes you make to it have no effect on the existing form. That happens again when you say new Leisure().
The myName property you are using changes the name private field of myLes instance and not the name private field of myEv instance created in the ItemSend_Click.
In an Object Oriented Language when you create an instance of a class, that instance has a copy of every non-static private/public variable declared in the class. So when you write
Leisure myLes = new Leisure();
you are creating an instance of Leisure class, but this instance, while inherithing from Events has a different set of internal variables and not the same variables of the current Event instance (myEv).
Looking at your code I suggest to create a third class called
public class EventFactory
{
public Event CreateEvent(string eventType, string eventName)
{
switch(enventType)
{
case "Leisure":
Leisure myLes = new Leisure();
myLes.eventNames(eventName);
return myLes;
// case Add other specialized events here:
// break;
default:
return null;
}
}
}
change your Events class removing the inheritance from Form1 (not needed as far as I can tell) and the method myEvent
now your ItemSend_Click could be written in this way
private void itemSend_Click(object sender, EventArgs e)
{
Events myEv = new EventFactory().CreateEvent(eventType, itemInput.Text);
formEventName = myEv.myName;
txtOutput.Text = "Event name is " + formEventName + "\r\n";
}
this works because Leisure derives from Events and you could treat every Leisure instance as an Event instance.
You just change myName of the myLes (Leisure) variable in your myEv field, thats why myEv.myName is still empty.
So the problem that you're having is just a small symptom of major fundamental problems in your code that will only continue to manifest themselves as you continue.
I've re-written what you have into something that's more in line with what is more traditionally seen for what you're trying to do. It's not perfect, and I've tried to keep things fairly simple so as to not throw too much at you at once.
public partial class Form1 : Form //Main form class
{
private TextBox itemInput;
private TextBox txtOutput;
private string eventType; //used for event type selection
private string formEventName; //used to store selected event name
private void itemSend_Click(object sender, EventArgs e)
{
string name = itemInput.Text;
try
{
Event myEvent = Event.Create(eventType, name);
txtOutput.Text = "Event name is " + myEvent.Name + "\r\n";
}
catch (ArgumentException ex)//if the event name isn't valid
{
MessageBox.Show(ex.Message);
}
}
}
public abstract class Event
{
public string Name { get; private set; }
public Event(string eventName)
{
Name = eventName;
}
public static Event Create(string eventType, string eventName)
{
if (eventType == "Leisure")
{
Leisure myLes = new Leisure(eventName);
return myLes;
}
// else if { ... } test for other event types
else
{
return null;
}
}
}
public class Leisure : Event
{
private static List<string> myEventNames =
new List<string>() { "music", "Music" };
public Leisure(string eventName)
: base(eventName)
{
if (!myEventNames.Contains(eventName))
{
throw new ArgumentException("Not a valid Leisure event name");
}
}
}
So, let's go over some of the changes. First off, Event doesn't inherit from Form1. It should not do so. An event is not conceptually a type of form at all, let alone that particular type of form. An Event should have no knowledge of any form, in any way, not just inheritance. It's just some other class that Form1 will use, but it could just as easily be used by any other type of class, form or otherwise.
In addition to making Event not inherit from Form, I've made it abstract. It doesn't have any abstract methods, it's just that you shouldn't ever be creating just an plain Event, you should only ever actually create some specific type of event. Being a common base class, it's easiest to prevent accidental creation and to help improve readability by making it abstract.
I've also made Event immutable. Rather than allowing name to be changed at any time, creating an event without giving it a name, and then changing it later, I have configured it such that you need to provide the name and type before creating the event, and then there's no way of changing it once it's created. The Name is set in the constructor, and I have added a static Create method which is where the logic can go for choosing the proper subtype of Event and actually creating it. This is a simple version of the "Factory Pattern". Note that normally I wouldn't pass the type in as a string. I would make it something like an Enum, so that it's easier to tell what the valid options are.
Now onto Leisure. Logically, Leisure really is an Event and should inherit from it. Your problems were steming from the fact that you created an instance of Event, and also an instance of Leisure, and assumed that they shared the same variables. They don't, but that confusion should go away now that you can't ever have an instance of Event.
When a Leisure is created it uses the base class constructor to set Name, since it doesn't have access to set the property itself.
From what I can see myEventNames is just a list of valid names, and it doesn't appear to change between different types of Leisure instances, so it makes sense for it to be static, which means it's shared between all instances and is only created once.
I also moved the MessageBox call out of the Leisure type's constructor. Instead I'm throwing an exception. The main idea here is that you shouldn't mix your UI code with your business code. Event and Leisure are both business objects and shouldn't know anything about what, if any, UI exists. You should be able to use them from a console app, an ASP application, etc. On top of that, since what we're trying to say is that this is an invalid name and the type shouldn't exist, the end result of throwing an Excpetion in the constructor is that the object never becomes "valid". We don't allow the creation of an object that shouldn't exist, as opposed to allowing them to continue using the object anyway.
That exception is caught with the try/catch block in Form1, where it shows the appropriate MessageBox based on the failure to create the event.
So I've been working on a class that details students of a university. I have one button that sets the details to a new instance of a class, and another to check if the student passed, through a method in my Class. The problem is that I create an instance of a class in the first button to add the values from what the user input, but I cannot use the second button to access the instance of the class created in the first button.
Try to make a property over the method like
private Student student1 {get;set;}
Then you can work with the instance you set in this property with
student1 = new Student();
You can make it public if you want to be able to access the property from outside of this class, and you can also make it static when the field should be accessible even without having an instance of the class you're actually working in (most likely a form).
Then, you should of course not create a new Student in your other button. When you set the property to a new student, your old student that you set the first time will be gone.
Static or Singleton classes should solve this.
http://msdn.microsoft.com/en-us/library/ff650316.aspx -Singleton implementation
The easier way are also class properties.
http://msdn.microsoft.com/en-us/library/w86s7x04.aspx - Class properties
Student student1; //**Simple Declare it here then**
private void button3_Click(object sender, EventArgs e)
{
student1 = new Student(); //**Create a new instance here**
**//BUT You need to handle the exception that can come if the user clicks //button1 before button 3** possibly like this
if(student1 == null)
return;
label1.Text = student1.text();
if (student1.hasPassed() == true)
{
passfailtextbox.Text = "Pass";
}
else
{
passfailtextbox.Text = "Fail";
}
}
private void button1_Click(object sender, EventArgs e)
{
Student student1 = new Student();
student1.FirstName = firstnamebox.Text;
student1.SecondName = secondnamebox.Text;
student1.DateofBirth = DateTime.Parse(dobtextbox.Text).Date;
student1.Course = coursetextbox.Text;
student1.MatriculationNumber = int.Parse(matriculationtextbox.Text);
student1.YearMark = double.Parse(yearmarktextbox.Text);
}
i've often had this issue where i do not really understand how to pass userform variables into classes. for example i have a button:
private void button1_Click(object sender, EventArgs e)
{
DoStuff();
}
and a method in the form class:
DoStuff()
{
Class123 myclass = new Class123();
}
...
...
class Class123
{
//how do i pass for example in myotherClass whether or not my checkbox on the userform is checked? i dont want to have to pass from method to method to class to class. what is the logical/smart way of handling this?
ClassData myotherClass = new ClassData();
}
how do i pass for example in myotherClass whether or not my checkbox on the userform is checked? i dont want to have to pass from method to method to class to class. what is the logical/smart way of handling this?
I think you are looking for function arguments:
// notice the declared function argument isMyCheckboxChecked
DoStuff(bool isMyCheckboxChecked)
{
Class123 myclass = new Class123(isMyCheckboxChecked);
}
private void button1_Click(object sender, EventArgs e)
{
// passing the state of the checkbox to DoStuff as an argument
DoStuff(chkMyCheckbox.Checked);
}
class Class123
{
readonly ClassData myotherClass = new ClassData();
Class123(bool isMyCheckboxChecked)
{
myOtherClass.isMyCheckboxChecked = isMyCheckboxChecked;
}
}
I can see a few things here. The code posted is rather vague, so it is hard to say what the correct answer may be.
If myOtherClass needs to know if a checkbox is checked when the checkbox changes then you should probably look into using a subscriber pattern.
However, if you mean that you just need to know if the checkbox was checked at the moment DoStuff() ran, there is nothing wrong about passing a variable. In fact, passing a variable is the preferred way - it's what variables exist for. That said, you need to pass variables intelligently; if you find that you are just slinging parameters across classes constantly, that's a sign of poorly-designed code. If you need to pass some parameters to myClass to tell it what to do, build them into a (descriptively named) class of their own, and pass that class to myClass's constructor instead of a long list of parameters.
I disagree with this approach.
Any 'smart' method, if it even exist, will break the golden rules of Object Oriented Programming.
An object is a self contained item of data that can only be accessed or changed in a controlled way. This prevents side effects, a common problem in procedural code, where data is globally accessible. In OOP, the objects can receive or send messages to other objects only by calling their methods.
EDIT: To show a way to do it
public static class MyApp
{
public static bool MyCheckBox {get; set;}
}
in your doStuff
MyApp.MyCheckBox = this.checkBox1.Checked;
inside a method of your myOtherClass
if(MyApp.MyCheckBox == true)
...
this is the same as using a global variable in the old days of procedural languages. This paves the way to difficult to track bugs and creates state mode that render an application hard to maintain