I have a method in my Form1.cs called GenerateComboBoxList() and I want to call this in the main method so that the contents of the combo box is generated when the application is started.
public void GenerateComboBoxList()
{
cmbServerDatabase.Items.Add("1");
cmbServerDatabase.Items.Add("2");
cmbServerDatabase.Items.Add("3");
}
However, when I begin to type GenerateComboBoxList() in the main method, intellisense does not pick this up. Can anyone help with where I am going wrong?
You need an instance of the Form1 in your Main method, only then you can call your method, but, don't do that. Instead call this method in your Form_Load event or overload OnLoad (See: this).
Your Main method in Program.cs should only be responsible for specifying/loading the start up form. Later in your Form's Load event you can do:
private void Form1_Load(object sender, EventArgs e)
{
GenerateComboBoxList()
}
You can do it after InitializeComponents() in a constructor of your form :
public Form1()
{
InitializeComponents();
GenerateComboBoxList();
... other things that you want to set on startup
}
P.S. other option that is already suggested by people here would be to use an Form_Load event handler.
Related
Let's say I have a Form called Form1 which will somehow (how is not relevant) calls another form Form2
(Form1)
Form2 f2= new Form2();
f2.ShowDialog();
This Form2 has a button that will do some operation everytime the user clicks on this button.
However, I want that the first time i.e. when Form2 is just shown, the code in the button (some operation) gets executed.
In other words I have to be able to call the code in Form2's button_Click which is private.
Now I can think of some ways to make this possible(making the click event public etc) , but my question is what is the most elegant (or correct) way to do this?
I would add a property to Form2 to tell the form I like to automatically executed an action.
class Form2
{
public bool AutoExecuteSomeOperation { get; set; }
}
In Form1, you would set that property and in Form2 you would check and execute appropriate code if the property was set.
I would recommend that you refactor button_Click to call another method which you can also call for automatic execution. I like to keep event handler simple and executed only for the event on the control that served to name the event handler. Thus, you know that button_Click is an handler for a Click event on a control named button. It makes the code easier to maintain.
You can decide if you want to reset the property once the code is executed or you can add some validation that the property changes are valid. For exemple, you might want to ensure that the property is called before displaying the form.
In all cases, you should avoid having any reference to a control from an external form. Only Form1 itself should know that it contains a button. Any use from outside world should be done through a public property or public event of the form. That way, if you decide that the button should be replaced by an hyperlink, a menu item, a checkbox or anything else Form1 does not need to be updated. This is very similar to what should be done for UserControl. The less internal details leak, the easier it will be to make internal changes without having to update all caller.
The easiest approach is just make it public, however its not the bastion of great design.
Decoupled messaging is probably where you want to be, event aggregator or any pub sub method messaging system. This is a more modern and scalable approach, the participants need not know about each other allowing you to make the methods private and giving you a more maintainable decoupled solution, and keep your classes self consistent.
Unity, MvvmLight both have these sorts of messaging systems, however there are lots of them.
Example of how this might work
public Form1()
{
InitializeComponent();
EventPublisher.Instance.Subscribe<NewUserCreated>
(n => listBoxUsers.Items.Add(n.User.Name));
}
...
// some other class
private void Form2()
{
var user = new User()
{
Name = textBoxUserName.Text,
Password = textBoxPassword.Text,
Email = textBoxEmail.Text
};
EventPublisher.Instance.Publish(new NewUserRequested(user));
}
Move the code from the OnClick event into its own method (e.g. "DoWork"), then call that method from the OnClick event.
Either call it when you create the form
var frm = new demoForm();
frm.DoWork();
frm.Show();
Or call it in the forms constructor.
public partial class demoForm : Form {
public demoForm() {
InitializeComponent();
DoWork();
}
private void button1_Click(object sender, EventArgs e) {
DoWork();
}
public void DoWork() {
//Code here
}
}
The form has a button and a panel with a UserControl which has a ListBox and a TextBox.
When I click the Windows.Form button it calls UserControl's Add()
listBoxTitles.Items.Add(metroTextBoxTitles.Text);
metroTextBoxTitles.Clear();
Which simply adds whatever the UserControl's TextBox.Text has to the UserControl's ListBox.
For some reason nothing happens when i click the button.
Why. Nothing on the UserControl can be changed or used? Or does it change but doesn't update/show what's going on?
The best way to deal with communication between containers is to implement an observer class
The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.
(wikipedia)
the way i do this is creating an Observer class:
1 public delegate void dlFuncToBeImplemented(int signal);
2 public static event dlFuncToBeImplemented OnFuncToBeImplemented;
3 public static void FuncToBeImplemented(int signal)
4 {
5 OnFuncToBeImplemented(signal);
6 }
so basically: first line says that there would be a function that somebody else will implement
second line is creating an event that occur when the delegated function will call
and the third line is the creation of the function that calls the event
so in your UserControl you should add a function like this:
private void ObserverRegister()//will contain all observer function registration
{
Observer.OnFuncToBeImplemented += Observer_OnFuncToBeImplemented;
/*and more observer function registration............*/
}
void Observer_OnFuncToBeImplemented(int signal)//the function that will occur when FuncToBeImplemented(signal) will call
{
MessageBox.Show("Signal received!", "Atention!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
and in your Form you should do something like:
public static int signal = 0;
public void button1_Click(object sender, EventArgs e)
{
Observer.FuncToBeImplemented(signal);//will call the event in the user control
}
and now, you can register this function to a whole bunch of other controls and containers and they will all get the signal
I hope this would help :)
So, what was happening was, when you create a UserControl and add it to the Window.Form the Form's designer already initiates that UserControl:
private UserControl userControl1;
So in order to solve the issue i just needed to use the UserControl which the designer code created:
usercontrol1.add();
And everything is working perfectly.
I am trying to figure out when exactly the Form.Load event occurs. In MSDN it sais:
Occurs before a form is displayed for the first time.
But when the form is displayed for the first time? My first instinct was immediately after InitializeComponent(), but when I tried the following code, the MessageBox showed 5 even though the value was set after InitializeComponent(), so it's not immediately after InitializeComponent():
public partial class Form1 : Form
{
private int number;
public Form1()
{
InitializeComponent();
number = 5;
}
public void Form_Load(object sender, EventArgs e)
{
MessageBox.Show(number);
}
}
So When does it occurs?
OnLoad is one of the methods being called when you call Show or ShowDialog on a Form.
The first time you call Show or ShowDialog, OnLoad is called and your Load event is fired. (Just like OnHandleCreated, etc.)
Have a read of https://msdn.microsoft.com/en-us/library/86faxx0d(v=vs.110).aspx
This explains the order of startup and shutdown of forms.
In short, a number of events are triggered in order - eg create...load...activate..shown ..
I have a Forms that is shown in a method called through Invoke because that method is called from a different thread. In the form I need to open I have a UserControl with a ComboBox in it. If the ComboBox.DropDownStyle is Simple the form.Show explodes throwing
InvalidOperationException: Cross-thread operation not valid: Control
'comboBox1' accessed from a thread other than the thread it was
created on.
If I set ComoBox.DropDownStyle in the default value (DropDown) I have no problem.
I now this is kind of hard to understand (even believe) so here there is a simplified example to reproduce it:
Create a new winforms project.
Create two forms and a user control.
In the user control create a ComboBox.
In the Form2 put an instance of the user control.
In the Form1 code put this:
private Form form;
private delegate void ShowDelegate();
private ShowDelegate showDelegate;
private void Form1_Load(object sender, EventArgs e)
{
showDelegate = Show;
new Thread(Run).Start();
}
private void Run()
{
form = new Form2();
Invoke(showDelegate);
}
private void Show()
{
form.Show();
}
Remember to set the event to Form1_Load.
Run it and see it working.
Change the ComboBox.DropDownStyle to Simple and see it not working!
Any help with this issue please?
By simply moving
form = new Form2();
To your Show() method, it will work then.
The Form gets initialized on the thread you start, it works then. But you might want to check the behavior in the long term ...
I'm trying to open a new form from within an event handler in the main form in a C# program. The event handler gets called properly and it opens the new form, but the new form is frozen and doesn't even initially populate.
I can create a button on the main form and have the new form created after the button is clicked, but it is not working properly when done from the event handler.
The event handler doesn't need to know the results of anything done on the form it creates - it just needs to create it and get out of the way.
What do I need to do? The new form needs to operate independently of the main form.
Here's where I define the event handler:
ibclient.RealTimeBar += new EventHandler<RealTimeBarEventArgs>(ibclient_RealTimeBar);
Here's the event handler code:
void ibclient_RealTimeBar(object sender, RealTimeBarEventArgs e)
{
FancyForm a_fancy_form = new FancyForm();
a_fancy_form.Show();
}
Creating a new form via a button click works fine:
private void button7_Click(object sender, EventArgs e)
{
FancyForm a_fancy_form = new FancyForm();
a_fancy_form.Show();
}
Can you post the event handler code?.. Also is the Event being raised in a seperate thread then the main ui?
Edit:
Not sure what the realtime bar does, but try checking for an invokerequired on your form so you can create the secondary form on the same thread as the main UI..
void ibclient_RealTimeBar(object sender, RealTimeBarEventArgs e)
{
if(this.InvokeRequired)
{
this.Invoke(((Action)() => ShowFancyForm()));
}
ShowFancyForm();
}
FancyForm a_fancy_form;
private void ShowFancyForm()
{
if(null != a_fancy_form)return;
a_fancy_form = new FancyForm();
a_fancy_form.Show();
}
Of course this uses some dirty shortcuts and assumes 3.5 but you can modify to your needs.
Also I moved the FancyForm decleration outside of the scope of the method.. again adjust to your needs.
i had the exactly same problem, i used Quintin's code and it works fine now....
I made some changes in order to work with the framework 2.0, here is what i did:
First, i created a delegate, pointing at the method that opens the form:
public delegate void pantallazo();
pantallazo obj=new pantallazo(this.ShowFancyForm);
The method that opens the form is the same one provided by Quintin:
smatiCliente a_fancy_form; //smatiCliente is the name of my new form class...
private void ShowFancyForm()
{
if (null != a_fancy_form) return;
a_fancy_form = new smatiCliente();
this.Hide();
a_fancy_form.Show();
}
And inside my programm's event handler, y made some simple changes:
if(this.InvokeRequired)
{
this.Invoke(obj);
}
ShowFancyForm();
And thats it, it works great now. The Invoke method executes the appropiate delegate, so the form is now created under the main UI.
Hope it works, and thanks a lot Quintin!
Do you know which thread is running in the event handler? I believe it might have to be the main GUI thread to work.