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.
Related
For example after creating a new Windows Form project I have my class called Form1.cs and from that form I can simply start typing the name of a form control and it will auto populate the form control variable names and I am able to use them in the class. However I have other classes that need to be able to access these form control variables as well, but they are not accessible.
Make them public if they are going to be used in another assembly, or internal if they are going to be used in the same project. Making them static means you don't have to pass your Form1 into the other classes.
Example... Say your Form1 has a string that contains the text you display in the title bar. Making it internal static, like this:
internal static readonly string MsgBox_Title = " Best Application Evar!";
lets you access it from other classes like this:
Form1.MsgBox_Title
It doesn't have to be readonly; that's just an example I pulled from an old app...
If you don't want static variables, you'll have to pass in an instance of Form1.
public class SomeClass
{
private Form1 m_Form1;
public SomeClass(Form1 form1)
{
m_Form1 = form1;
}
private void someMethod()
{
string localValue = m_Form1.SomeMemberStringVariable;
}
}
It's a very contrived example, but hopefully you get the idea.
If you want to call the Refresh method from a class instantiated from Form1, you could use an event in the child class to notify Form1.
Example:
This Form1 has a button that I use to show a secondary form.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnShowPopup_Click(object sender, EventArgs e)
{
PopupForm f = new PopupForm();
f.CallRefreshHandler += PopupForm_CallRefreshHandler;
f.ShowDialog();
}
private void PopupForm_CallRefreshHandler(object sender, EventArgs e)
{
Refresh();
}
}
The secondary form, "PopupForm", has a button that I use to raise an event that the Form1 is subscribed to, and lets Form1 know to call Refresh.
public partial class PopupForm : Form
{
public event EventHandler CallRefreshHandler;
public PopupForm()
{
InitializeComponent();
}
private void btnRaiseEvent_Click(object sender, EventArgs e)
{
EventHandler handler = CallRefreshHandler;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
}
Hope this helps.
Create an object of that class & start using those variables like this
Form1 fm = new Form1();
string abc = fm.VAR;
Define a public property in your form.
public string MyProp { get; set; }
Form1 frm = new Form1();
frm.MyProp = "Value";
Or define the property as static to avoid having to instantiate Form1:
public static string MyProp { get; set; }
Form1.MyProp = "Value";
I ran into this issue recently. I was keeping some methods in a separate class. Maybe not a good design decision in my case, I'm not sure yet. And these methods sometimes needed to communicate with controls in the main Form1. For example, to write to textBox1.
Turns out easy enough. Just write your method signature to include a TextBox instance. For example you pass textBox1 in and inside the method you refer to it as tb. Then when you call that method (even though it is in another class) you set the tb.Text property to whatever you like and it will show on textBox1.
This makes sense when you consider that control is just a special kind of object, graphically represented in the Form. When you pass it as an argument to a method in another class or the same class, you are actually passing the reference. So writing text to it in the method call will write text to the original control.
I have one main form and a static class when i access static class member it gives me nullreference error . Previously it was working fine donot know what happend . Any one can suggest what is wrong.
code snap:
namespace MyNamespace
{
public partial class myForm : Form
{
public myForm()
{
InitializeComponent();
}
private void myForm_Load(object sender, EventArgs e)
{
My_Static_Data_Class.player_name="Demo Player"
}
}
public static class My_Static_Data_Class
{
public static string player_name = "";
}
}
please help?
You're either accessing the static class member before it was set to "Demo Player". For example, you are trying accessing My_Static_Data_Class.player_name in Program.cs code before it calls the main form from the Main[] method. Alternatively you're might be setting My_Static_Data_Class.player_name to null elsewhere in code and then accessing it.
Check all the references in code editor and follow it up. To do this, right click on My_Static_Data_Class.player_name in Visual Studio editor, and choose Find All References menu item.
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.
I have a class 'App' which has instances of both a 'DeviceManager' class and a windows form 'MainForm' stored as fields.
MainForm is made visible by clicking a system tray icon. DeviceManager has Docked and Undocked methods, with Docked starting a synchronization operation. The Docked method should only start the operation if the MainForm is not visible.
DeviceManager doesn't have access to App's members, so it can't use App's reference to MainForm to check the form's status. Having App pass itself into DeviceManager's constructor seems like a lot of coupling when DeviceManager has no other need for such a reference (MainForm and DeviceManager are thus far unaware of each other).
I'm now considering having the setter of the App.IsUserActive property raise an event that DeviceManager can use to maintain its own 'IsUserActive' field.
Are there any other approaches I could look into?
Edit: added code to illustrate:
internal class App
{
private DeviceManager _deviceMgr;
private MainForm _mainForm;
internal App()
{
_deviceMgr = new DeviceManager();
_mainForm = new MainForm { Visible = false };
}
}
internal class DeviceManager
{
private void Docked()
{
if (!_mainForm.Visible) //can't see MainForm or App from here
{
Connect();
StartSynchronization();
}
}
private void Undocked()
{
Disconnect();
}
}
There is a global reference to the forms you can use.
Here's a quick example:
//Inside of DeviceManager class
private bool CheckFormVisibility<TForm>() where TForm : Form
{
TForm form = System.Windows.Forms.Application.OpenForms.OfType<TForm>().SingleOrDefault();
return form != null && form.Visible;
}
Then call CheckFormVisibility<MyForm>() or remove the generics and use specifically for your MyForm.
**I'm going under the assumption here that you will only have zero/one instance of a form.
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.