Application.OpenForms.Count = 0 always
There's a bug in Windows Forms that makes a form disappear from the Application.OpenForms collection. This will happen when you assign the ShowInTaskbar, FormBorderStyle, ControlBox, Min/MaximizedBox, RightToLeftLayout, HelpButton, Opacity, TransparencyKey, ShowIcon or MdiParent property after the window was created. These properties are special in that they are specified as style flags in the native CreateWindowEx() call. This sample form demonstrates the bug:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
button1.Click += button1_Click;
}
private void button1_Click(object sender, EventArgs e) {
Console.WriteLine(Application.OpenForms.Count);
this.ShowInTaskbar = !this.ShowInTaskbar;
Console.WriteLine(Application.OpenForms.Count);
}
}
Windows Forms must call CreateWindowEx() again to make the changed property effective, passing different style flags. Destroying the original window first has side effects beyond the very noticeable flicker, one of them is that the Application class loses track of the form since it sees the window disappear. With the bug that it doesn't add it back when the new window is created. Avoid the bug by setting the property only in the constructor, code that runs before CreateWindowEx() is called, not in any event handlers.
In general, avoid relying on OpenForms due to this bug. Give the class that needs to display the message box a reference to the form instance through its constructor. MessageBox usually figures out a parent window by itself correctly btw, it will pick the active window and that's correct 99% of the time. If you need it to call BeginInvoke() from a worker thread then be sure to copy SynchronizationContext.Current in your constructor and call its Post() method later. Ensures your library will also work with other GUI class libraries.
Is there any other way to access open forms in C#?
Isn't really necessary a name to get an open form.
You can get the form you want by index:
Form frm = Application.OpenForms[0] //Will get the main form
Form frm = Application.OpenForms[1] //Will get the first child
Forms in the OpenForms collection are ordered in the same way that you create it
Otherwise, an alternative is to save a reference to the form and then accessing it by this reference.
//Where you want to save the reference:
Form theForm;
//Where you create the form:
myClass.theForm = new MyForm();
//Where you want to get that form:
MessageBox.Show(myClass.theForm.Caption);
(myClass is the class that will hold your reference to the form, supposing you are accessing it from different classes)
(Also, see if you are affected by this: Application.OpenForms.Count = 0 always)
is there a way to prevent a form to show multiple times in #c?
You could check the collection OpenForms from the Application object
if(forge.Checked)
{
successfully_injected openForm = Application.OpenForms.OfType<successfully_injected>().FirstOrDefault();
if(openForm == null)
openForm = new successfully_injected();
openForm.Show();
}
else
{
select_option openForm = Application.OpenForms.OfType<select_option>().FirstOrDefault();
if(openForm == null)
openForm = new select_option();
openForm.Show();
}
this.Close();
C# alternative to (Application.OpenForms[0] as Form1)
If your Class1 instance doesn't already have a reference to the Form1 instance then there is not other way. That begs a couple of questions though.
Firstly, if that Class1 object needs to directly affect that Form1 instance then why doesn't it already have that reference? Where did that Class1 object come from? Most likely the Form1 instance created it. If so, why didn't Form1 pass a reference to itself into the Class1 object when it was created?
Secondly, why is that Class1 object directly affecting the Form1 instance anyway? Most likely a better design would be for the Class1 object to raise an event that Form1 can handle and then affect itself.
How to check if a windows form is already open, and close it if it is?
maybe this helps:
FormCollection fc = Application.OpenForms;
foreach (Form frm in fc)
{
//iterate through
if (frm.Name == "YourFormName")
{
bFormNameOpen = true;
}
}
Some code in the foreach to detect the specific form and it could be done. Untested though.
Found on http://bytes.com/topic/c-sharp/answers/591308-iterating-all-open-forms
iterate through open forms and close particular forms only
You can use LINQ to find the forms you want to close and List.ForEach
to close them:
Dim ActiveFroms = New List(Of String) From {"FrmSale", "FrmpPurchase", "FrmpSaleReturn", "FrmPurchaseReturn"}
Dim formsToClose = From form In My.Application.OpenForms.Cast(Of Form)()
Join activeFormName In ActiveFroms
On form.Name Equals activeFormName
Select form
formsToClose.ToList().ForEach(Sub(form) form.Close())
You cannot use a For Each
with the query above because Form.Close
will modify the collection which is not allowed. Therefore i use List.ForEach
.
Related Topics
Visual Studio 2010 Suddenly Can't See Namespace
Getting Data from Stored Procedure with Entity Framework
What Is the Best Data Type to Use for Money in C#
Using Filesystemwatcher to Monitor a Directory
How to Automatically Filter Out Soft Deleted Entities with Entity Framework
Tolist()-- Does It Create a New List
Formatting Doubles for Output in C#
Using Global Keyboard Hook (Wh_Keyboard_Ll) in Wpf/C#
ASP.NET MVC 5 Group of Radio Buttons
Best Way to Remove Duplicate Entries from a Data Table
How to Get the Exif Data from a File Using C#
Requested Registry Access Is Not Allowed
If Statements Matching Multiple Values
Is There a Generic Constructor with Parameter Constraint in C#