Can't add to a RichTextBox from another class? - c#

I have a main form called FormMain.
FormMain has a RichTextBox inside of it called mainConsole.
I created a method inside of FormMain:
public void ConsoleAdd(String text)
{
mainConsole.AppendText(text);
mainConsole.AppendText(System.Environment.NewLine);
}
I changed the property Modifiers of mainConsole to Public.
Now in another class I wrote this in a button control:
FormMain fMain = new FormMain();
fMain.ConsoleAdd("Success!");
But it doesn't work. There is no exception raised, and there is no text added either.
Am I doing something wrong?

The problem I see is that you call ConsoleAdd on the wrong reference. It seems like you create a new reference of FormMain and call ConsoleAdd on this one. If you call
fMain.Show();
you would see a second window pop-up with the text in the RichTextBox. You have to pass the reference to the correct FormMain to the function trying to call ConsoleAdd or use a Singleton.

This is how I solved it:
In the FormMain I added this code:
static FormMain instance;
public FormMain()
{
InitializeComponent();
instance = this;
}
public static FormMain Instance
{
get
{
return instance;
}
}
And in the other class I called the method like this:
FormMain fMain = FormMain.Instance;
fMain.ConsoleAdd("Success!");
Thanks for the answers everybody!

Related

Create Windows Form as Class Library

I am trying to make a windows form to be reused across several projects. So I thought this would be a class library. What I want to do is call WindowsForm.Show() as a static call. I've tried to create a class library but I cannot reach the resources for an icon. I then created a WinForms project, but it wants a 'New' in the program.cs. I do not want to call
WindowsForm form = new WindowsForm()
form.show()
How do i create a reusable static form? I hope i'm being clear.
To add a factory method you can do:
public static MyForm ShowNew()
{
MyForm form = new MyForm();
return form;
}
About resources, it depends on what you're using the icon for. If the icon is always the same and it always will be, then add it to your library Properties/Resources (if you don't see it, go on your library project properties, on the tab Resources, and click add). Otherwise, add a parameter to your factory method (and to the form constructor as well) and pass it when you call the form:
public static MyForm ShowNew(Icon ico)
{
MyForm form = new MyForm(ico);
return form;
}
When instantiating
MyForm.ShowNew(Properties.Resources.my_icon);
Another approach would be implementing your form as usual, wrapping it in a Singleton-like class :
public static class WindowsFormSingleton {
// A static instance of your form
private static WindowsForm _form;
// A singleton property to interact with the form.
public static WindowsForm Instance
{
get
{
if(_form == null) {
this._form = new WindowsForm();
}
else if(_form.IsDisposed) {
this._form = new WindowsForm();
}
return this._form;
}
}
}
... and using the singleton instance like the following :
WindowsFormSingleton.Instance.Show();
Note: As taffer stated in the comments, using a Factory method to always create a new instance would be a better approach to this.

Calling a variable from a global class

I have a class for global variables, like this:
internal static class GlobalVariables
{
public static PortBrowserForm open;
}
The PortBrowserForm class is a Windows Form class that has a timer and want to use its properties, like this (in another form):
// In that other form...
GlobalVariables.open.timer1.Enabled = true;
But I cannot call it. I can only call a function from GlobalVariables.open variable (which is a form already). Please help.
GlobalVariables.open.timer1.Enabled = true;
To make the above code work you need to make the timer1's modifier public or atleast internal. But... Don't do that, never expose fields public because you don't get control over who is doing what.
Instead create a method which does the job for you.
class PortBrowserForm : Form
{
public void SetTimerEnabled(bool enabled)
{
timer1.Enabled = enabled;
}
}
Then use
GlobalVariables.open.SetTimerEnabled(true);
Quick and Dirty
Check PortBrowserForm .designer.cs/vb file there you can find the declaration of all controls of the form. Change its access level to public from there and you can access that from any form just by creating forms instance.
Update:
To access one forms control in another you need to pass the first form in the constructor of another. Suppose we have two forms
Form1.cs
Form2.cs
In some event of form1 , call form2.
frm1Btn_Click()
{
form2 f2 = new form2(this);
f2.Show();
}
Create a overloaded constructor in form2 with Form1 as parameter and pickup form1 and its all controls.

How to access a visual component from another form in c#

I have a textbox in my main form.
Now I have created a function which is used to set the value of the text box.
public void SetTextOfTextBox(String text)
{
textbox1.text = text;
}
Now in my main form I call another class (class b) which does some work for me. Now i want to be able to call my setTextofTextBox function from class b.
Now if I try Form1.SetTextOfTextBox("test"); this doesn't work.
What am I doing wrong?
How do I access components of a a Form from another class.
Form1.SetTextOfTextBox("test"); this doesn't work
This doesn't work because SetTextOfTextBox is not static and you cannot access a non-static function directly. And you can't make it static either because your textbox is form level control.
How do I access components of a a Form from another class
You will have to pass the instance of Form1 to your other class to access it. Something like
Class B = new ClassB(this); //where this is the instance of Form1.
You will need a reference to the instance of Form1 in class b, otherwise you cannot call member methods.
Something like this:
class Form1 : System.Windows.Forms.Form {
void functionInForm1() {
ClassB objB = new ClassB();
objB.doSomething(this);
}
}
class ClassB {
void doSomething(Form1 form) {
form.SetTextOfTextBox("test");
}
}
Find out the Form1 and call the method:
foreach (var form in Application.OpenForms) {
Form1 myForm = form as Form1;
if (!Object.ReferenceEquals(null, myForm)) {
myForm.SetTextOfTextBox("Test");
break;
}
}
Did u try using delegates.
Specify the delegates in your ClassB like this.
public delegate void OnDone(string textValue);
public event OnDone OnUserDone;
after completing the task in ClassB call event:
OnUserDone("DoneClassB");
When u create the object of class in form map delegate function.
Classb b=new Classb();
b.OnUserDone += new Classb.OnUsrControlDone(CompletedClasss);
Define the function in form like below.
void CompletedClasss(string textValue)
{
SetTextOfTextBox( textValue);
}

An object reference is required for the non-static field, method or property error

I am developing a C# windows form application and on the main form I have a TabControl. It is declared in the Form1.Designer.cs file as follows:
public System.Windows.Forms.TabControl logFileCollectorTabControl;
In another class file in my project I want to use this TabControl as follows:
logFileCollectorForm.logFileCollectorTabControl.TabPages.Add(newTabPage);
But I get the error 'An object reference is required for the non-static field, method or property error'. So my question is, there must be an object of the Form class declared somewhere because the form launches when I launch the application, so how do I find out what that is, or how can I solve this issue, any help is greatly appreciated!
This is usually overcome by passing in an instance of Form1 to the constructor of the calling class, then keeping it in a field until needed.
//somewhere in Form1
OtherClass other = new OtherClass (this);
// OtherClass.cs
class OtherClass {
Form1 _opener;
public OtherClass(Form1 opener) {
_opener = opener;
}
}
Is your other class aware of logFileCollectorForm?
If you do not pass a reference to the form to the other class, then the other class does not know what Is logFileCollectorForm is referencing.
//example of another class
class AnotherClass
{
Form1 logFileCollectorForm;
public AnotherClass(Form1 logFileCollectorForm)
{
this.logFileCollectorForm = logFileCollectorForm;
}
public DoSomething(String newTabPage)
{
logFileCollectorForm.logFileCollectorTabControl.TabPages.Add(newTabPage);
}
}
There is probably no need to pass an instance of an entire form, you could pass a reference to your TabControl only. But it's still bad design in my opinion. Your logic should be separated from UI. If your class performs some computations, database operations or what not, it shouldn't really have to "know" about your window at all, because this is inflexible. Implement an event instead.
Another option is to keep a static reference to the main form in the Program class.
static class Program
{
internal static Form1 MainForm { get; set; }
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
MainForm = new Form1();
Application.Run(MainForm);
}
}
class OtherClass
{
public void AddNewTab(TabPage newTabPage)
{
Program.MainForm.logFileCollectorTabControl.TabPages.Add(newTabPage);
}
}

Call panel.invalidate outside form class in C#

I need to call "panel.invalidate" outside my form (WINform) class also I need to change some other controls as well, I read similar question here, and tried what they said, but it didn't work and I wasn't convinced at all.
The answer I read was about exposing a public method like this:
public void EnableButton(bool enable)
{
this.myButton.Enabled = enable;
}
Also I made a static instance in the other file
static Form1 myForm = new Form1();
Any useful suggestions??
The problem is the "myForm" reference. It is a reference to an instance of Form1 that isn't visible and doesn't match the one that the user is looking at. It can't be a match, you created a new one.
Whatever class needs to update the form must have a constructor that takes a Form1 reference. You can create the class object in your Form1 constructor or Load event, pass "this". Using Application.OpenForms[0] is another way to get the reference, one you should not use.
Are you updating from the same thread? Otherwise you might need to use Invoke.
Here's a nice short article about how to do that:
http://blogs.msdn.com/csharpfaq/archive/2004/03/17/91685.aspx
Control.Invalidate() is a public method, but the control itself is most likely not public. You will have to expose the call to Control.Invalidate() through a public facing method in your form or by marking the control in question as public.
public class MyForm : Form {
private TextBox tbxName = new TextBox();
public InvalidateTextBox() {
tbxName.Invalidate();
}
}
OR
public class MyForm : Form {
public TextBox tbxName = new TextBox();
}
public class SomeOtherClass {
public void InvalidateTextBox(MyForm form) {
form.tbxName.Invalidate();
}
}

Categories

Resources