"Cross-thread operation not valid" if ComboBox.DropDownStyle == Simple - c#

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 ...

Related

How to check from the beginning in Windows Forms App

_Changed events check it if it is changed. How can I check it from the beginning.
private void dateTimePicker1_ValueChanged(object sender, EventArgs e)
{
if (dateTimePicker1.Value.Month == 2)
{
pictureBox1.Visible = true;
}
else
{
pictureBox1.Visible = false;
}
}
You can call the event handler from the constructor, or sometimes better, the Load of the form:
private void MyForm_Load(object sender, EventArgs e)
{
dateTimePicker1_ValueChanged(dateTimePicker1, EventArgs.Empty);
}
There is also the Shown event called after the window first appears on the desktop.
Thus the control will be initialized as expected.
Here is the chain of calls:
Constructor : prefered place to instantiate objects and initialize UI instances.
Load : prefered place to create and initialize non designer UI objects or complete them like populating combobox or dataset.
Activated : prefered place to do things each time the form is activated and get focus.
Shown : prefered place to do things after the form is showned like open another form or show a info box.
The difference between using constructor, load or shown is mainly to have a clean code design and a smooth UI behavior.
There is no real difference between putting code in the constructor or in the load, else the reference and window handle are created.
Order of Events in Windows Forms (MS Doc)

Windows forms Form closed event not working with opening a new form

I have some code meant to open a new windows form when one is closed, and yet I get nothing, no error.
I've tried a few different methods for opening a new form on a Form.FormClosed event.
This is the code I have right now:
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
Form1 myForm = new Form1();
myForm.Show();
}
But yet I get no error, nothing.
I'm expecting for a new windows form to be opened when I close another one.
Any help would be appreciated, thanks!
The problem is that as soon as the first Form1 instance closes, your application shuts down and exits because the application message loop is defined with the initial Form instance, and it is just waiting for events on that form until it closes. On closing, the application will exit, opening a new form doesn't stop this process.
You need to adjust the Main() method in Program.cs to look something like this:
[STAThread]
static void Main()
{
// ... Application configuration as required here
new Form1().Show(); // The first form instance is now no longer bound to the Application message loop. Start it before we begin the run loop
Application.Run(); // Don't pass in Form1
}
Your original code should now work. I might add however, this is not a great user experience. Carefully consider what you're trying to achieve, and perhaps consider alternatives - do you just need a "reset form" button? Or is the primary goal to prevent a user from closing the application? If the latter, you can remove the Close icon altogether.
Perhaps something simple to get your going forward.
private Form1 myForm = new Form1(); //Declare the form as a private member variable
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
e.Cancel = true; //Cancel the closing so this object stays alive
this.Visible = false; //Hide this form
myForm.Show(); //Show the next form
}
Please note #pcdevs comment. You'll need a way to indicate the form is being closed/application quiting vs progressing to the next step/form. You might want to look at some CodeProject articles about "C# Winform Wizards", those sequential dialog prompt apps...

Calling user created method in Form1 in Main()

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.

C#/.NET - WinForms - Instantiate a Form without showing it

I am changing the Visibility of a Form to false during the load event AND the form still shows itself. What is the right event to tie this.Visible = false; to? I'd like to instantiate the Form1 without showing it.
using System;
using System.Windows.Forms;
namespace TestClient
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
this.Visible = false;
}
}
}
Regardless of how much you try to set the Visible property before the form has been shown, it will pop up. As I understand it, this is because it is the MainForm of the current ApplicationContext. One way to have the form automatically load, but not show at application startup is to alter the Main method. By default, it looks something like this (.NET 2.0 VS2005):
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
If you instead do something like this, the application will start, load your form and run, but the form will not show:
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Form1 f = new Form1();
Application.Run();
}
I am not entirely sure how this is useful, but I hope you know that ;o)
Update: it seems that you do not need to set the Visible property to false, or supply an ApplicationContext instance (that will be automatically created for you "under the hood"). Shortened the code accordingly.
I know this is an old question, but I just stumbled upon it and am pretty surprised no one has mentioned SetVisibleCore:
bool isVisibleCore = false;
protected override void SetVisibleCore(bool value)
{
base.SetVisibleCore(isVisibleCore);
}
In that code snippet, as long as isVisibleCore remains false, the form will remain invisible. If it's set to false when the form is instantiated, you won't get that brief flash of visibility that you'd get if you set Visible = false in the Shown event.
It took me some time to find a properly working Solution.
Set the properties named WindowState to Minimized and ShowInTaskbar to False under properties window. Once your form is completly loaded, Call below lines of code.
this.ShowInTaskbar = true;
this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
//this.WindowState = System.Windows.Forms.FormWindowState.Normal;
PS: This solution is Tested on Visual C# 2008 Express Edition
How about setting the Opacity property to 0 on design and back to 100 when you want to show the form?
a solution i can live with
so the form is created and on_load is called on createtion.
set WindowState to minimize then on load set visible to false and windowstate to normal
private void Form1_Load(object sender, EventArgs e)
{
this.Visible = false;
this.WindowState = FormWindowState.Normal;
}
what did not worked:
the SetVisibleCore override solution did not created the form
as also the
Application {
Form1 f = new Form1();
Application.Run();
):
For a flicker-free Shown solution, also set the form's location off-screen during load:
private Point startuplocation;
private void Form1_Load(object sender, EventArgs e)
{
this.startuplocation = this.Location;
this.Location = new Point(-1000, -1000);
}
private void Form1_Shown(object sender, EventArgs e) //fires first time shown
{
this.Visible = false;
this.Location = this.startuplocation;
}
Just create an instance of Form1 and do not call methods to show/display it. But I bet you're doing something wrong.
Try on the VisibleChanged event.
The shown event may give you want you want. Although the form will "flash" for a second before hiding.
private void Form1_Shown(object sender, EventArgs e)
{
this.Visible = false;
}
What I would suggest would be to instantiate the form in an event the precedes the _Show event, such as the constructor, after the IntializeComponent() call.
If this is your main form, there may not be a better place then the Shown event. But in that case you will get flicker.
I couldn't find a good place to stop a running main form from showing at least quickly. Even a timer activated in the load event won't do it.
If it is a secondary form just create it but don't show it.
Have you tried
this.Hide();
in the form_load or form_activated events
Set the visibilty on the constructor, after init and then this.Show() later
InitializeComponent() is setting this.Visible = true, since you specified that the form should be visible in the designer (or it defaulted to that). You should set Visible to false in the designer, and it won't be called by InitializeComponent(). You can then make it visible any time you like.
Having .Visible = false or Hide() in the Load event will cause your form to show briefly, as there is time between when it becomes physically visible and when the Load event gets fired, in spite of the fact that the documentation says the contrary.
Are you calling Show() or ShowDialog() somewhere? I'm not sure if this behavior is still present, but at least in past versions of the framework a call to ShowDialog() did not trigger the Load event, so perhaps that is your issue (though I think calling ShowDialog() then hiding a modal form would be a bad practice!)
If you have to have the handle created (and the handles for controls) for whatever it is you're trying to do, a better idea would be to set the StartLocation to Manual, then set the Position property to an offscreen location. This will create and show the form, while making it invisible to the user.
Yeah the really one elegant way in perspective to your code than your applications visual is to flicker the form by hiding in the constructor/load event.
I set these three property settings for the form:
ShowInTaskbar = false
ShowIcon = false
WindowState = Minimized

Opening New Form From Event Handler in Main Form Hangs App

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.

Categories