I am working on c# window forms and stuck since long ago to solve a situation.
The situation is :
I have a GUI Form1.cs[Design] which consists of a Button and textbox (txtmsg here).
I have created a class Testing.cs in the visual studio winform project which contains the code like this :
namespace smallTesting
{
class Testing
{
public Testing()
{
MessageBox.Show("Connection String Did not found");
Form1 frm = new Form1(); //I do this in order to have access to
//renderMessage() so that i will be able to update my output to
//textbox(txtMsg) in this function definition by calling it.
int i = 1;
for(;;)
{
if (i == 50)
{
break;
}
frm.renderMessage(i.ToString());
i++;
}
}
}
}
And Form1.cs class is:
namespace smallTesting
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnStart_Click(object sender, EventArgs e) //It should work on button click.
{
btnStart.Enabled = false;
Testing tst = new Testing();//Instantiate the class
}
private void btnClose_Click(object sender, EventArgs e)
{
this.Close();
}
public void renderMessage(string str)
{
this.txtMsg.Text = str;
MessageBox.Show("str :" + txtMsg.Text); //It should update my Textbox by 1 to 50 . BUT IT DONT DO.Whereas i can see the counting in the message box popuped.
}
}
}
I was expecting the function call to renderMessage(string str) from class Testing must have updated the txtMsg but it don't do so. Why ? (whereas messagebox popuped shows that the string is updated for every call to this function) . Why the txtMsg is not updated in my GUI for each call? How to update it.
Note: Please note that this txtMsg box updation mechanism must go from testing.cs to Form1.cs (Not Form1.cs to Testing.cs)
Change your Testing class to receive the instance of Form1 that you want to update the textbox
namespace smallTesting
{
class Testing
{
public Testing(Form1 currentInstance)
{
MessageBox.Show("Connection String Did not found");
int i = 1;
while(i < 50)
{
currentInstance.renderMessage(i.ToString());
i++;
}
}
}
}
Now in the Form1 constructore change how do you initialize the Testing instance
namespace smallTesting
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnStart_Click(object sender, EventArgs e) //It should work on button click.
{
btnStart.Enabled = false;
// Pass the reference of the instance of Form1 that you
// want to update. Do not let the Testing class creates its
// own instance of form1, instead use THIS ONE.
Testing tst = new Testing(this);
}
......
}
}
Related
I'm working on a project that contains multiple pages in the same window and i made that using multiple User Controls docked on top of each other and when you click the page button it shows up using: userControl1.Show(); / userControl1.Hide();.
I'm facing some problems when i try to access a combobox text that is located on the form1, i have tried using public strings such as:
public string comPort;
private void cbPort_SelectedIndexChanged(object sender, EventArgs e)
{
comPort = cbPort.Text;
}
and trying to access it from the other user control using:
Form1 mainForm;
public FiremwareFlasher()
{
InitializeComponent();
mainForm = (Form1)this.FindForm();
}
and then:
MessageBox.Show(mainForm.comPort);
But i got that error:
System.NullReferenceException: 'Object reference not set to an instance of an object.'
Any ideas?
You could define string property and use Application.OpenForms method to access the property.
Here is a code example you can refer to.
In form1:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
comboBox1.Items.Add("test1");
comboBox1.Items.Add("test2");
comboBox1.Items.Add("test3");
comboBox1.Items.Add("test4");
testUcl1.Hide();
}
public string cmbtext
{
get
{
return comboBox1.Text;
}
set
{
comboBox1.Text = value;
}
}
bool t = true;
private void button1_Click(object sender, EventArgs e)
{
if(t)
{
testUcl1.Show();
t = !t;
}
else
{
testUcl1.Hide();
t = !t;
}
}
}
In Usercontrol:
public partial class TestUcl : UserControl
{
public TestUcl()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form1 form1 = (Form1)Application.OpenForms["Form1"];
textBox1.Text = form1.cmbtext;
}
}
Test Result:
I am learning C# and have run into an interesting issue to me. I have a class variable defined as public and I instantiate a new instance of my form in my class and access the value of the public variable it is always null.
To further explain my issue - this syntax prints the appropriate value
System.Diagnostics.Debug.WriteLine(tboxvalue.ToString());
However, this syntax is always outputting a 0
System.Diagnostics.Debug.WriteLine(f1.tboxvalue.ToString());
How do I need to alter my syntax so that the correct value is passed to the class Functions?
public partial class Form1 : Form
{
public double tboxvalue;
private string exportdata;
public Form1()
{
InitializeComponent();
}
private void btnClicker_Click(object sender, EventArgs e)
{
Functions.EE();
}
private void txtData_CheckedChanged(object sender, EventArgs e)
{
bool #checked = ((CheckBox)sender).Checked;
if (#checked.ToString() == "True")
{
exportdata = "Yes";
tboxvalue = Convert.ToDouble(this.txtData.Text);
System.Diagnostics.Debug.WriteLine(tboxvalue.ToString());
}
else
exportdata = "No";
}
}
class Functions
{
public static void EE()
{
Form1 f1 = new Form1();
System.Diagnostics.Debug.WriteLine(f1.tboxvalue.ToString());
}
}
To access properties of the form, you need to change two Things. First you have to pass the form to the 'EE' method, then you can access the form's properties. Second, don't create a new form in 'EE' method.
public partial class Form1 : Form
{
public double tboxvalue;
private string exportdata;
public Form1()
{
InitializeComponent();
}
private void btnClicker_Click(object sender, EventArgs e)
{
Functions.EE(this);
}
private void txtData_CheckedChanged(object sender, EventArgs e)
{
bool #checked = ((CheckBox)sender).Checked;
if (#checked.ToString() == "True")
{
exportdata = "Yes";
tboxvalue = Convert.ToDouble(this.txtData.Text);
System.Diagnostics.Debug.WriteLine(tboxvalue.ToString());
}
else
exportdata = "No";
}
}
class Functions
{
public static void EE(Form1 f1)
{
System.Diagnostics.Debug.WriteLine(f1.tboxvalue.ToString());
}
}
If i understood your question i guess you are recreated Form1 with own textbox or labels when you click btnClicker button. You can reassign your form objects where you created it.
You might add static Form1 object and Setter routine to Functions class:
private static Form1 _form;
public static void SetForm(Form1 form)
{
_form = form;
}
and pass the form to the class in Form_Load event-click on the form twice:
private void Form1_Load(object sender, EventArgs e)
{
Functions.SetForm(this);
}
Then you can play with the form in Functions class using the object _form
good luck!
This is my code. Problem is explained bellow. What I'm trying to do is implement hash map object re-usability in Java to C# using dictionary.
Form 1
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 bb = (Form2)UiFac.loadUi();
}
}
Form 2
public partial class Form2 : Form
{
int a = 1;
public Form2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Console.WriteLine(a.ToString());
a++;
}
private void button2_Click(object sender, EventArgs e)
{
Application.ExitThread();
}
public Form2 getForm2()
{
return this;
}
}
and the UiFac class
public class UiFac
{
public enum UiName
{
LOGIN,
HOME
}
static Dictionary<UiName,Form> map = new Dictionary<UiName, Form>();
public static Form loadUi()
{
Form theForm;
map.TryGetValue(UiName.HOME, out theForm);
if (shit == null)
{
Form2 bb = new Form2();
Console.WriteLine("Inside if " + bb.GetHashCode());
map.Add(UiName.HOME, bb);
bb.Show();
}
else
{
map.TryGetValue(UiName.HOME,out theForm);
Console.WriteLine("Inside else " + shit.GetHashCode());
Form2 ff = (Form2)theForm;
ff = ff.getForm2();
ff.Show();
}
return theForm;
}
}
I did this using Hash Maps in java and it works perfectly. Then I got the need to do the same using C#. When I press Button1 in Form1 for the fist time Form2 loads. But when I close it and again press Button1 in Form1 it throws System.ObjectDisposedException' in System.Windows.Forms.dll
What am I missing?
thank you!
If you call Close() on a form it will be disposed eventually by the framework. Use the Hide() method instead.
From the docs:
When a form is closed, all resources created within the object are released and the form is disposed.
As NightOwl stated in the comment I advice you when the application is closed you loop trough the dictionary and close or dispose all the forms present to avoid resource leaks. You can do that by implementing the IDispose interface in the UiFac class and call Dispose on all forms in the collection:
public sealed class UiFac : IDisposable
{
...
public void Dispose()
{
// Call dispose on all forms
}
}
On closing Form1 call UiFac.Dispose();
I have created one form and two .cs files.
1st file form1.cs:
namespace WindowsFormsApplication4
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private Class1 _enemy;
private void button1_Click(object sender, EventArgs e)
{
_enemy = new Class1(this);
_enemy.LoopInteration += OnLoopInteration;
_enemy.MyMethod();
_enemy.LoopInteration -= OnLoopInteration;
}
private void OnLoopInteration(object sender, LoopCounterArgs e)
{
textBox1.Text = Convert.ToString(e.Iteration);
}
}
}
second file class1.cs:
namespace WindowsFormsApplication4
{
public class LoopCounterArgs : EventArgs
{
public int Iteration { get; set; }
public LoopCounterArgs(int iteration)
{
Iteration = iteration;
}
}
public class Class1
{
public event EventHandler<LoopCounterArgs> LoopInteration;
public Class1(Form1 form)
{
_form1 = form;
}
public void MyMethod()
{
for (int j = 1; j <= 20; j++)
{
LoopInteration?.Invoke(this, new LoopCounterArgs(j));
//Thread.Sleep(100);
}
}
private Form1 _form1;
}
}
and the form design of form1:
Form1 Design
Now am getting the following errors in this:
*Error 1:
Invalid expression term '.' c:\users\43060\documents\visual studio
2013\Projects\WindowsFormsApplication4\WindowsFormsApplication4\Class1.cs 29 32 WindowsFormsApplication4
Error 2:
Syntax error, ':' expected c:\users\43060\documents\visual studio
2013\Projects\WindowsFormsApplication4\WindowsFormsApplication4\Class1.cs 29 33 WindowsFormsApplication4*
What I want is that when user clicks button on form1 the for loop runs in class1.cs and result is displayed in form1 text box.
Strictly want to use Event + Delegation model.
It should be like that remove "?"
LoopInteration.Invoke(this, new LoopCounterArgs(j));
I have no idea about how this error was made. Here's my code and error.
I created a new form in solution explorer and wrote these codes in my main form. I'm sure that the hitbox which I used below is right.
public partial class HomePageForm : Form
{
OptionsPageForm frmOptions;
}
private void HomePageForm_MouseClick(object sender, MouseEventArgs e)
{
if (this.homePageOptionsButtonHitBox.Contains(e.Location))
{
this.Enabled = false;
frmOptions = new OptionsPageForm(this);
frmOptions.Show();
}
}
And these are codes i wrote in my "frmOptions" - which is the form i want to call.
public partial class OptionsPageForm : Form
{
OptionsPageForm frmHomePage;
public OptionsPageForm(HomePageForm frmCreator)
{
InitializeComponent();
frmHomePage =frmCreator;
}
}
The error given by visual studio is:
Cannot implicitly convert type "My Application_.MainPageForm" to "My Application_.OptionsPageForm".
And this is another form-calling I did in this application, it has the same structure as my call to frmOptionsPage, but it works perfectly.
public partial class HomePageForm : Form
{
GamePageForm frmGame;
}
private void HomePageForm_MouseClick(object sender, MouseEventArgs e)
{
if (this.homePageStartButtonHitBox.Contains(e.Location))
{
this.Hide();
frmGame = new GamePageForm(this);
frmGame.Show();
}
}
(In Gamepage form)
public partial class GamePageForm : Form
{
HomePageForm frmHomePage;
public GamePageForm(HomePageForm frmCreator)
{
InitializeComponent();
frmHomePage = frmCreator;
}
}
I now really want to get some help, please.
I think you need to move you Mouse Click event handler into the class like this
public partial class HomePageForm : Form
{
GamePageForm frmGame;
private void HomePageForm_MouseClick(object sender, MouseEventArgs e)
{
if (this.homePageStartButtonHitBox.Contains(e.Location))
{
this.Hide();
frmGame = new GamePageForm(this);
frmGame.Show();
}
}
}