I don't want to create an object because it won't affect my visible form. How can I call a method so it does its thing in the visible side of things.
public class foo
{
public void SetString(string foo)
{
label1.Text = foo;
}
}
Inside another class:
foo X = new foo();
X.SetString("testlololol");
This will set the label, but VIRTUALLY, I won't be able to see it on my form.
How can I do the same thing, but on my VISIBLE side of things?
When you create your visible form store a references to it in some static property. Then other classes can use that property to run public methods of that class.
// the original form
class MyForm()
{
// form public method
public void MyMethod() { ... }
}
// class storing the reference to a form
class MyOtherClass
{
public static Form MyForm;
public void ShowForm()
{
MyForm = new MyForm();
MyForm.Show();
}
}
// invoke form public method in this class
class YetAnotherClass
{
public void SomeMethod ()
{
MyOtherClass.MyForm.MyMethod();
}
}
You need to somehow get the instance which is visible. Work out some information path from things that already know about your form (or whatever it is) to your other code. Consider what would happen if there were two visible forms - which one would you want? That should suggest a way forward. If you know for a fact that there'll only ever be one visible instance, you could use a singleton - but I'd strongly suggest that you don't.
Bear in mind that you may not need to know of it by its full type name - if this is crossing layers, you may want to work out some interface including the action in some abstract way.
I would usually either pass a reference of my form ('foo' in this case) to the other class. Or I would store off a copy of 'foo' to some static location. If you know that there will only ever be 1 instance of 'foo' you could do something like:
public class foo
{
public static foo Current { get; private set; }
public foo()
{
foo.Current = this;
}
public void SetString(string foo)
{
label1.Text = foo;
}
}
...and...
foo.Current.SetString("testlololol");
Though thats a bit hacky IMO, and doesnt support multiple instances of 'foo'.
Your second class needs to have a reference to the instance of the class that IS visible.
public class OtherClass{
foo myFoo;
public OtherClass( foo visibleFoo )
{
myFoo = visibleFoo;
}
public void method()
{
myFoo.SetString("testlolol");
}
}
Related
I have a method in my Mainwindow, i want to call this method in an other usercontrol.
I dont use a static method because my MainWindow is not Static, and I can't make it static.
So I figured out to use this, but I dont know what comes behind the AS and I dont know if I can put a method is VAR?
I also can't make another MainWindow instance because that gives me a Stackoverflow exception.
How can I solve this?
var myMethode= mainWindow.FindName("MyMethode") as (should be a methode);
if (myMethode!= null)
{
//My code
}
You can define a static method on a class that is not static.
For example:
static void Main()
{
Foo foo = new Foo();
Foo.DoSomething();
foo.DoSomethingElse();
}
public class Foo
{
public static void DoSomething()
{
Console.WriteLine("DoSomething");
}
public void DoSomethingElse()
{
Console.WriteLine("DoSomethingElse");
}
}
But wouldn't it be a better solution to pass the MainWindow as a parameter into the User Control? So the user controls knows to which window it belongs and can access a function on it? (even better to declare an interface for this and pas the interface around).
This would look like:
public interface IWindow
{
string SomeWindowActivity();
}
public class MyUserControl
{
public IWindow Window { get; set; }
public void SomeActionOnUserControl()
{
string data = Window.SomeWindowActivity();
}
}
public class MainWindow : IWindow
{
MyUserControl MyUserControl { get; set; }
public MainWindow()
{
// Link the UserControl to the Window it's one. This can be done trough the
// constructor or a property
MyUserControl.Window = this;
}
public string SomeWindowActivity()
{
// Some code...
return "result";
}
}
Try this
((MyMainWindow)Application.Current.MainWindow).Method()
You don't need to make MainWindow singleton in your case, you have access to it from Application.Current singleton
Application.Current.MainWindow
Hope this helps
Short unswer: you can't. You want to call a instance method, you need to have an instance.
The fact that MainWindow is not static does not prevent you from defining static methods in it, as long as those methods do not use other instance members, so if it a helper method, you can define it static and call from other place, it might a good idea to refactor it out of MainWindow class then.
If it's a nonstatic method, you claim you don't want to create second instance of MainWindow, why not call it on first instance then, by passing it to your control?
Also, if creating another instance of MainWindow gives you stackoverflow, maybe it's because you just did some recurrent call with this method, and it can be fixed?
Updated to reflect to my own source
I'm in process of building my first winform application in c# and I'm trying to figure out the best practice for structuring my classes to work smoothly when I use them in my forms.
I have a couple of examples which I will try to explain the best way i can.
When working with get/set variables in a class, the best practice should be something like this:
JobMove.cs
public class JobMove
{
private List<string> jobNames { get; set; }
public string Scanner;
public JobMove()
{
this.Scanner = Properties.Settings.Default.Scanner;
}
public void ListSelected(ListBox lbx)
{
foreach (string jName in this.jobNames)
{
lbx.Items.Add(jName);
}
}
public static List<string> GetCheckedJobs(ListView lw)
{
int countChecked = lw.CheckedItems.Count;
int itemCount = 0;
List<string> jList = new List<string>();
foreach (ListViewItem item in lw.CheckedItems)
{
JobInfo jobInfo = Job.Find(Convert.ToInt32(lw.Items[item.Index].SubItems[1].Text));
jList.Add(jobInfo.Name);
itemCount++;
}
return jList;
}
}
My problem is when I combine this with my forms and I call this, then I would try to do something like this:
MyForm1.cs
public partial class MyForm1 : Form
{
private void btnMoveJobs_Click(object sender, EventArgs e)
{
Properties.Settings.Default.Scanner = cbxScanners.SelectedItem.ToString();
JobMove moveJobs = new JobMove();
frmMoveJobs FrmMoveJobs = new frmMoveJobs();
FrmMoveJobs.ShowDialog();
}
}
MyForm2.cs
public partial class frmMoveJobs : Form
{
public frmMoveJobs()
{
InitializeComponent();
JobMove moveJobs = new JobMove();
lblFrom.Text = moveJobs.Scanner;
moveJobs.ListSelected(lbxJobsToMove);
cbxMjScanners.DataSource = System.Enum.GetValues(typeof(Scanners));
}
}
But when I call MyClass in MyForm2 and I want to call the DoSomethingElse method, then myString will be reset to a null value. And that makes sense to me, but how do I work around this?
I tried to figure out what to use here to get easier around these flaws in my code, but my knowledge is far too weak to just implement an easy solution.
I know I could just store this variable in Settings.settings as an example, but to me that just seems like a real overload for such a simple task.
I might just need a point in the right direction to right on what to do in this situation.
If you do a MyClass myClass = new MyClass(); then indeed - the values are independent and unrelated. If you want to share the MyClass instance then pass the MyClass instance between the forms. Perhaps:
using(var form2 = new Form2()) {
form2.SensibleName = existingMyClassInstance;
form2.ShowDialog();
}
(note the using above btw; when using ShowDialog() it is your job to make sure the form is disposed; it only gets disposed automatically if using Show())
Firstly, they're properties, not variables (the variables are the underlying data source).
Secondly, the whole point of get/set accessors is so you can get and set the value without needing helper methods.
Thirdly, and as to your problem, you're creating a new instance of the class in each form (hinted at by the new keyword) and the value of the property will be whatever it is initialised as on construction of the instance (or not.) i.e. the values of properties are not shared between different instances of the same type.
Think of the mold for a key: I can get multiple instances of the key cut from a "blueprint", but any damage that one suffers won't be reflected by the rest - they're unique in that sense.
If you want the forms to both access the same instance of that type, then you will need to stash the instance somewhere in your code which is accessible to both.
A few options:
Pass in an instance of MyClass in the form2's constructor.
Make MyClass a static property of either Form1 or Form2 and access it via that on the other form.
Make MyClass static (not recommended).
If you want to use the instance of MyClass created in MyForm1 inside of MyForm2, you need to provide it to MyForm2.
Something like this would work:
public partial class MyForm2 : Form
{
public MyForm2(MyClass given)
{
InitializeComponent();
given.DoSomethingElse();
}
}
Easy Solution:
private static string myString { get; set; }
Why: because you initialize the class again when initializing Form2 and it will create a new class. With the "static" keyword you create a property which is the same in all instances of this class.
BUT: please read some books before continuing, this would be the solution to this problem, but the source of many others. Try to understand C# and Forms first, than (or alongside with reading/learning) start coding!
this is because each of your form has a new object of "MyClass".
To achieve what you want to do use a static property... this won't be initialized and gives back the same value for each object of MyClass
it looks like this
public class MyClass {
public static string myString { get; set; }
public void ChangeMyString(string newString)
{
myString = newString;
}
public void DoSomethingElse()
{
MessageBox.Show(myString);
}
}
This should be quite simple really - not sure what the problem is.
I have a C# Class (Public.cs) and a windows form (Form1.cs). Through a function in Public.cs, I want to get the value of a control on Form1 (without having to use object parameters).
// This code appears in Public.cs
public string MyFunction(int num_val)
{
if (chk_num.checked == true)
{
// Something here...
}
}
The issue is that my class cannot find the control on my form. Is there some way that I must reference it in C#?
Thank you.
I would strongly suggest exposing the Checked property via a specific property on Form1 (perhaps with a more meaningful name). This will help to hide the implementation details (i.e. control structure) of the Form1 from it's caller and instead expose only the logic that is required for other consumers to do their job
For example:
public bool IsNumberRequested
{
get { return chk_num.Checked; }
}
Or alternatively, if you still really want to access the control directly, from the designer you can select the control and change it's Modifier property to public (or something else) enabling you to access the control object using the code you originally wrote above.
EDIT: (Response based on comment)
Public.cs will still need a reference to Form1 and then will call the IsNumberRequested property of that object.
// Public.cs
public class Public
{
private Form1 _ui;
public Public(Form1 ui) { _ui = ui };
public string MyFunction(int num_val)
{
if (_ui.IsNumberRequested)
{
// Stuff
}
// Else, default Stuff
}
}
Alternatively, you could pass the form as a parameter to the MyFunction too rather than using it as an instance variable.
I would have the set up the other way around
public class Public
{
public bool CheckNumber {get;set;}
public string MyFunction(int val)
{
if(CheckNumber)
{
//do that thing
}
return ...
}
}
public partial class Form1 : Form
{
Public myinstance = new Public();
public Form1()
{
InitializeComponent();
}
private void CheckBoxChanged(object sender, EventArgs e)
{
myinstance.CheckNumber = chk_num.checked;
}
}
You'll need to assign CheckBoxChanged to the OnChanged event handler for your check box (which I'm assuming is chk_num.
This way your class Public doesn't rely on a form, which it shouldn't.
As Reddog says, use better names, although I half suspect you've just given example names in your question.
I am trying to use a method inside class, from another class.
namespace Crystal.Utilities
{
public class Logging
{
public static void Log()
{
//dostuff
Crystal.MainForm.general_log_add_item("Hello World");
}
}
}
namespace Crystal
{
public partial class MainForm : Form
{
public void general_log_add_item(string msg)
{
listBox1.Items.Add(msg);
}
}
}
I want to be able to call Crystal.Utilities.Logging.Log() from anywhere, and that to be able to call Crystal.MainForm.general_log_add_item() . But It doesn't let me, because if I put it as public, then I can't see it, if it's static then It can't interact with my listbox.
This is a wrong approach. Your class should not call into the UI, as the UI could change. The class should not know nor care about the UI. Instead, the class could expose an event that the form could subscribe to, and update based upon the information contained within the event's arguments.
Here's a hastily thrown together example.
class Program
{
static void Main()
{
Logger.OnLogging += Logger_OnLogging;
Logger.Log();
Logger.OnLogging -= Logger_OnLogging;
}
static void Logger_OnLogging(LoggingEventArgs e)
{
Trace.WriteLine(e.Message);
}
}
public class Logger
{
public delegate void LoggingEventHandler(LoggingEventArgs e);
public static event LoggingEventHandler OnLogging;
public static void Log()
{
// do stuff
RaiseLoggingEvent("Data logged");
}
protected static void RaiseLoggingEvent(string message)
{
if (OnLogging != null)
OnLogging(new LoggingEventArgs(message));
}
}
public class LoggingEventArgs : EventArgs
{
public LoggingEventArgs(string message)
{
this.Message = message;
}
public string Message { get; private set; }
}
Instead of implementing it as a static method, try implementing as a singleton. It's a common trick to make an instance global in scope, and restrict to one instance, without making everything static (and thus unable to be used as an instance).
You have to understand that the window is not static, there is one instance of him, thats why the method cant be static,
you can use
Application.Windows to reach this instance and call the add method.
or you can register the window in his constructor on another class that will mediate the Logging and the window.
If you don't understand tell me and I'll try to be more clear
When you declare a method as "static" you're saying that it's not dependent upon a specific instance of the class it's in.
For example if you have a class named "chair" and you want to count how many chairs there are, you'll do that with a static field, and a static method to return that field's value.
The count of all chairs is not related to a specific chair.
In your case you want to add a static method to add an item to a specific instance of a Form. That's impossible and doesn't make sense.
If you want to add an item to a listBox, it must be through a public method.
So basically what I'm saying is - rethink what you're trying to do, there's a good explanation as to why you're not succeeding in doing that.
The case is this, I have two different forms from the same solution/project. What I need to do is to extract the value of a label in Form A and load it into Form B. As much as possible, I am staying away from using this code since it will only conflict my whole program:
FormB myForm = new FromB(label.Text);
myForm.ShowDialog();
What I am trying right now is a class with a property of get and set for the value I wanted to pass. However, whenever I access the get method from FormB, it returns a blank value.
I hope somebody can help me with this. Any other ways to do this is extremely appreciated. :)
public class Miscellaneous
{
string my_id;
public void SetID(string id)
{
my_id = id;
}
public string GetID()
{
return my_id;
}
}
You could do something like this:
Child form
public string YourText { get; set; }
public TestForm()
{
InitializeComponent();
}
public void UpdateValues()
{
someLabel.Text = YourText;
}
Initiate it
var child = new TestForm {YourText = someTextBox.Text};
child.UpdateValues();
child.ShowDialog();
With this approach you don't have to change the Constructor, you could also add another constructor.
The reason for them being empty is that the properties are set after the constructor, you could Also do someting like this to add a bit of logic to your getters and setters, However, I would consider not affecting UI on properties!
private string _yourText = string.Empty;
public string YourText
{
get
{
return _yourText;
}
set
{
_yourText = value;
UpdateValues();
}
}
In this case, the UI will be updated automaticly when you set the property.
You can use a static variable/method to hold/pass the value of a control (when it gets changed).
You can use form reference or control reference to get and pass values directly.
You can use custom event for that (notifying the code that subscribed).
btw. FormB myForm = new FromB(label.Text); did not work because you are passing by value and the value was empty at the moment of creation of FormB.
FormB myForm = new FromB(label); would have worked.
Well one approach to take is to create a singleton class in your application. When you form b loads or the label changes you update the singleton with the value. Then when form a needs the value it can just get the instance of the singleton within your application and it will have that value.
There are probably cleaner ways to do it but just thinking of an easy way to pass information back and forth and store any information needed for both forms.
EDIT: Here is an example of a singleton that I pulled from here:
http://www.yoda.arachsys.com/csharp/singleton.html
public sealed class Singleton
{
static readonly Singleton instance=new Singleton();
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Singleton()
{
}
Singleton()
{
}
public static Singleton Instance
{
get
{
return instance;
}
}
}
Now all you need to do is put this class in a namespace that is accessible to both forms and then you can call the Instance property of this class and then reference your values. You can add properties to it as well for whatever you want to share. When you want to retrieve those values you would call it like this:
Singleton.Instance.YourProperty
((Form2)Application.OpenForms["Form2"]).textBox1.Text = "My Message";
declare public property varible in second form
Public property somevariable as sometype
and access it in first form using instance
Dim obj as New form2()
obj .somevariable ="value"