It's easy to access sub-window's objects from main file because we must create the sub window anyway. So there's something like this:
SubForm subform = new SubForm();
if (subform.ShowDialog() == DialogResult.OK)
{
text = subform.textBox1.Text;
//...
}
But I have some troubles with editing a combobox (placed inside main form) by a sub-cs file. I can't simply create a new main window. I've edited Program.cs file:
static class Program
{
public static MainForm mainform; //main window reference
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(mainform = new MainForm());
}
}
Now I can access the combobox:
Program.mainform.comboCurves.Items.Add("test");
Is it any better solution for this?
You can also pass a reference to your mainform directly into your subform, at least your main form won't be available to your whole application :
MainWindow.cs :
SubForm subform = new SubForm(this);
SubForm.cs :
public partial class SubForm : Form
{
private MainForm mainForm;
public SubForm(MainForm mainForm)
{
InitializeComponent();
this.mainForm = mainForm;
}
}
So now you can access it like mainForm.comboCurves.Items.Add("test");
Also, a better way would be to have your main form inherit form an interface that exposes only the necessary stuff :
public partial class MainForm : Form, IRestrictedInterfaceOfMainForm
{
public void AddStuff(string stuff)
{
comboCurves.Items.Add(stuff);
}
}
public interface IRestrictedInterfaceOfMainForm
{
void AddStuff();
}
public partial class SubForm : Form
{
private IRestrictedInterfaceOfMainFormmainForm mainForm;
public SubForm(IRestrictedInterfaceOfMainFormmainForm mainForm)
{
InitializeComponent();
this.mainForm = mainForm;
}
}
That way you only access what you really need and don't play directly with MainForm's controls. For example, if you want to change comboCurves to an array of textboxes, the second form won't even notice it.
Your solution works, but you should always try to expose the least amount of information, which is partly covered by the Interface segregation principle, from the SOLID principles.
Related
I've tried the bellow code which is working but it keeps opening multiple forms every time i call calltest() method. How can i call test() method without opening it's form? Should i move all my methods to another class file? Thanks
namespace test1
{
public partial class MainForm : Form
{
public void test()
{
//code
}
...
}
}
namespace test1
{
public partial class SecondForm : Form
{
private void calltest()
{
MainForm form1 = new MainForm();
form1.test();
}
...
}
}
You might want to reconsider your design. However, here is a direct answer to your question:
The issue you are having is because each time in the calltest method, you are creating a new instance of MainForm.
Instead, you should inject the original instance of MainForm and store it inside an instance variable inside SecondForm like this:
public partial class SecondForm : Form
{
MainForm form1 = null;
public SecondForm(MainForm main_form)
{
form1 = main_form;
}
private void calltest()
{
form1.test();
}
...
}
Now when you create your instance of SecondForm, make sure that you inject the original instance of MainForm with something like this:
SecondForm second_form = new SecondForm(main_form); //If you are creating this from MainForm, then simply pass `this` as the construction parameter
I'm having some issues accessing and modifying a listbox control from another class.
Here's the MainForm, which holds the listbox:
public partial class MainForm : Form
{
private static MainForm mainForm = new MainForm();
internal static MainForm init()
{
return MainForm.mainForm;
}
public MainForm()
{
InitializeComponent();
}
}
And here's the second class that I'm using to attempt to modify the listbox (the items are added from an event):
public class Utils
{
void ItemsReceived(object sender, DataReceivedEventArgs<ListboxItems> e)
{
MainForm.init().listBox1.Items.Add("test");
}
}
Using this code setup, nothing is added to the listbox. Any ideas? Or even a better way to tackle this?
Typically visual studio generates the following code in a Program.cs file:
Application.Run(new MainForm());
If this line still exists, your static mainForm variable will hold a different instance of MainForm than the one visible when running the application. If I'm right, change the line in Program.cs to:
Application.Run(MainForm.init());
On a side note, while using the singleton (anti)pattern, consider changing the name of that method to GetInstance() because init() appears to initialize something.
I don't know if I've made this messy or not......
I have an MDI parent created thus:
namespace APRSTW
{
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainAPRSTW()); //<= key call
}
}
}
In MainAPRSTW.cs, you find this....
namespace APRSTW
{
public partial class MainAPRSTW : Form
{......lots of stuff here, and the MDI parent happens here.......}
Now we have the parent MDI form. Next is the class that starts the process of creating the child form.
namespace TeleDecoder
{
class TDecoder
{......}
A new instance of TDecoder also creates a new instance of the following form
namespace ChildNode
{
public partial class Node : Form
{......}
with the code
ChildNodeForm = new Node();
ChildNodeForm.MdiParent = ?????????;
The question is, what do I use for "?????????" ?
Or, do I need to make some name changes?
I hope I got this across well.
Chuck
When you do this:
Application.Run(new MainAPRSTW());
you need to store a reference to that form:
public static Form mainForm;//at top of module
mainForm = new MainAPRSTW();
Application.Run(mainForm);
and then you can do
ChildNodeForm.MdiParent = mainForm;
I'm working on a Windows Forms application in C# with Visual Studio 2010.
There is a form mainForm.
mainForm contains a tree view control xmlTreeView.
There is a self-written class myClass.cs.
Now, myClass needs to access the xmlTreeView. However I don't know a) how to access the form and b) which way would be best to do that.
I tried to implement an interface following oleksii's answer but I don't get it. The main form of the application is defined like this:
public interface IMainForm {
TreeView treeView { get; }
}
public partial class mainForm : Form, IMainForm {
public TreeView treeViewControl {
get { return myTreeViewControl; }
}
// Some code here
[...]
RuleTree rt = new RuleTree(); //How do I call this with the IMainForm interface???
}
Another class RuleTree is defined like this:
class RuleTree {
private readonly IMainForm mainForm;
public RuleTree(IMainForm mainForm) {
this.mainForm = mainForm;
}
}
How do I call the constructor of RuleTree with the IMainForm interface???
I would do the following. Don't see it as code, it's just so that you can understand, you can modify it accordingly.
public class MyClass
{
public void MyMethod(YourTreeViewControl treeview)
{
// Do what you need to do here
}
}
Then in your forms code behind just instantiate MyClass and pass an instance of your treeview to it, something like this:
MyClass myClass = new MyClass();
myClass.MyMethod(tvYourTreeViewControl);
Hope this makes sense :)
One of the possible approaches would be to use dependency injection here. MyClass would have a constructor that takes a Form parameter. Thus when you create MyClass it would have the form injected. For example:
Foo
{
Foo(){}
}
Bar
{
private Foo currentFoo;
Bar(Foo foo) //dependency injection
{
currentFoo = foo;
}
public void OtherMethod()
{
//do something with currentFoo
}
}
It will be better to use interfaces (or abstract classes), so instead of Foo you could inject IFoo, this largely decouples your classes, which is a good design decision.
I have commented my code please read comments, I can make solution available as well.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
///
//Declare a static form that will accesible trhought the appication
//create form called frmMain form or any other name
//
public static frmMain MainForm { get; private set; }
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
//comment out default application run
//Application.Run(new MainForm());
//create a new instance of your frmMain form
//inside your main form add a tree view
//Loacte this file "frmMain.Designer.cs"
//Change treeView1 from private to public
// public System.Windows.Forms.TreeView treeView1;
MainForm = new frmMain();
//before I show my form I'll change docking of my tree view from myClass
MyClass mine = new MyClass(); //done
MainForm.ShowDialog();
}
}
public class MyClass
{
public MyClass()
{
Program.MainForm.treeView1.Dock = DockStyle.Fill;
}
}
}
This is not possible to access asp.net server side controls into other class other then their cs class e.g
test.aspx is a page
you can access test page controls only in test.aspx.cs
Other then this class this is not possible.
Can someone please let me know by some code how I can call a function located in the Form class from another class?
Some code will be of great help!
thanks
EDIT: This is my current code
public partial class frmMain : Form
{
//*******Class Instances*******
ImageProcessing IP = new ImageProcessing();
//********************
public void StatusUpdate(string text)
{
tlsStatusLabel.Text = text;
}//
public frmMain()
{
InitializeComponent();
}//
}
class ImageProcessing
{
private void UpdateStatusLabel(frmMain form, string text)
{
form.StatusUpdate(text);
}//
private UpdateLabel()
{
UpdateStatusLabel(frmMain, "Converting to GreyScale");
}
}
the problem i am having is with frmMain.
A quick and dirty way is to create a reference of the MainForm in your Program.cs file as listed above.
Alternatively you can create a static class to handle calls back to your main form:
public delegate void AddStatusMessageDelegate (string strMessage);
public static class UpdateStatusBarMessage
{
public static Form mainwin;
public static event AddStatusMessageDelegate OnNewStatusMessage;
public static void ShowStatusMessage (string strMessage)
{
ThreadSafeStatusMessage (strMessage);
}
private static void ThreadSafeStatusMessage (string strMessage)
{
if (mainwin != null && mainwin.InvokeRequired) // we are in a different thread to the main window
mainwin.Invoke (new AddStatusMessageDelegate (ThreadSafeStatusMessage), new object [] { strMessage }); // call self from main thread
else
OnNewStatusMessage (strMessage);
}
}
Put the above into your MainForm.cs file inside the namespace but separate from your MainForm Class.
Next put this event call into your MainForm.cs main class.
void UpdateStatusBarMessage_OnNewStatusMessage (string strMessage)
{
m_txtMessage.Caption = strMessage;
}
Then when you initialise the MainForm.cs add this event handle to your form.
UpdateStatusBarMessage.OnNewStatusMessage += UpdateStatusBarMessage_OnNewStatusMessage;
In any UserControl or form associated with the form (MDI) that you want to call, just us the following...
UpdateStatusBarMessage.ShowStatusMessage ("Hello World!");
Because it is static it can be called from anywhere in your program.
You can do that in easy way:
1- create public class and define public static variable like this:
class Globals
{
public static Form1 form;
}
2- in load function at the form write this line:
public partial class Form1 : Form
{
private void Form1_Load(object sender, EventArgs e)
{
Globals.form= this;
}
public void DoSomthing()
{
............
}
}
3- finally, in your custom class you can call all public functions inside the form:
public class MyClass
{
public void Func1()
{
Globals.form.DoSomthing();
}
}
I hope this code will be useful to you:)
It's quite easy. Either pass a reference to an existing form in the call, or create a new instance of your form and then call your method just like any other:
public class MyForm : Form
{
public void DoSomething()
{
// Implementation
}
}
public class OtherClass
{
public void DoSomethingElse(MyForm form)
{
form.DoSomething();
}
}
Or make it a static method so you don't have to create an instance (but it won't be able to modify open form windows).
UPDATE
It looks like the ImageProcessing class never gets a reference to the form. I would change your code slightly:
class ImageProcessing
{
private frmMain _form = null;
public ImageProcessing(frmMain form)
{
_form = form;
}
private UpdateStatusLabel(string text)
{
_form.StatusUpdate(text);
}
}
And then one small tweek in the Form constructor:
ImageProcessing IP = new ImageProcessing(this);
You will have to create a new Form instance and then call it using the instance. If it is static then you can just call it by calling Form1.Method().
Form1 form1 = new Form1();
form1.Method();
I would suggest you move this common method to some other class.
If it is common method to be used in the UI then create a base Form class and derive all your forms with this base form class. Now move this common method to the base form. You can then use the method from any of the Form derived from it.
If the method is not related to the UI, an from your example i understand that it's not, you can create another class that will contain this method and then use it in your Form class and in any other places where you want to use it.