Instantiated Form Does Not Open (replaced by VS default form) - c#

I have a Winforms app written in C#.
On one form there is a button which on the Click event opens a second form using the following code -
frmConflicts check = new frmConflicts(c);
check.Show();
frmConflicts has lots of controls on it, yet the Form which opens on the click event is a default Visual Studio form. By that, I mean the very small blank form which VS gives you when you Add New Item and select Form. There are no controls on it.
I've stepped through my code and the frmConflicts constructor is called, so I can't understand why a blank form is appearing instead.
Any clues?

Is the method initializing your Controls (like InitializeComponents) called at any time (like in your constructor) ?

Try setting the TopLevel property to True:
frmConflicts check = new frmConflicts(c);
check.TopLevel=true;
check.Show();

Related

Multi form Projects in c# - Displaying multiple windows

My main form is this
Now my problem occurs when I click Add -> Student, which is meant to bring up a new window that, instead it does this
So as you can see it opens the new form inside the same window. It didn't use to do this, then I made the main form an MdiContainer and set it as the MdiParent of the second form.
Is there a property I can change to make this new form pop up in a new window? Becuase I need to leave the MdiContainer property as True so that I can take data from Form2 and use it in Form1
Please let me know any other information you may need to help me fix this issue, as I'm not sure what caused it so I don't know what to change in order to fix it or even where I'm meant to be looking
you need to hide form enroll
when you open add window add.show()
you need to hide enroll form enroll.hide()

how to set up multiple form project with stack-like navigation

I'm struggling to find how to set up a multiple form project in Visual Studio with stack-like organization(ie undo,redo history / back,forward web browser/ mobile app navigation). So far, I have multiple forms that are related to each other but the subsequent item opens as a new window rather than replacing its preceding form.
That is to say that every time I click a button to navigate to the next page, a new window is generated with content when I'd rather have the content load on the same window, much like how web browsers usually behave.
There seems to be How to have a user navigate multiple "screens" within one form/window? which mentions MDI, which from what I've gathered is ideal for creating a situation where multiple sub-windows are created in one main window, which is different from what I'm shooting for. Although I'm building this using Visual Basic, I imagine that my issue is not tied to a specific .net language as it is tied to the GUI toolbox items in Visual Studio itself. Any assistance would be much appreciated.
Convert each form into a user-control and place all of those on a panel on a main-form and use their visibility property to hide and show as you need.
3 Steps to convert
1. Create New control,
2. copy all the textboxes etc from the old form to the control designer
3. copy the code behind as appropriate.
Then do a build, the control should appear in the toolbox for the main form
If each "page" depends on other pages, you may need to add methods to each control to handle that.. Like
Public Sub Refresh_Controls() or some such
NOTE:
You may only want to make the BODY part be on the user-control. The Navigation arrows etc should probably be their own "common" controls.
BTW: You could also do this by putting everything on the same form, with nested table layout panels, hiding or showing the appropriate panel. However, that gets really hard to work with in Visual studio if there are a lot of pages. It is a little easier to maintain with user-controls.
Try the following in a new project. Create a new VB Forms project. Before doing anything to it, create a User Control using "Project" | "Add User Control...". Give it the name "StackingControl". Add the following variables for the class:
Private TopText As New Label()
Private OurFormStack As New Stack(Of Form)()
In the "New" method after "InitializeComponent()" add:
TopText.Text = "The stack is empty"
Controls.Add(TopText)
We are creating a label ("TopText") and adding it to the User Control. I will explain later why we are doing that in code instead of the designer.
Also add the following methods:
Public Sub AddForm(ByVal f As Form)
If OurFormStack Is Nothing Then
Throw New ApplicationException("FormStack is null")
End If
Controls.Clear()
OurFormStack.Push(f)
f.FormBorderStyle = FormBorderStyle.None
f.TopLevel = False
f.ShowInTaskbar = False
f.Visible = True
f.Dock = DockStyle.Fill
Controls.Add(f)
End Sub
Public Sub RemoveForm(ByVal f As Form)
If OurFormStack Is Nothing Then
Throw New ApplicationException("FormStack is null")
End If
Controls.Clear()
If OurFormStack.Pop() IsNot f Then
Throw New ApplicationException("The current form is not being removed")
End If
If OurFormStack.Count = 0 Then
Controls.Add(TopText)
Return
End If
Controls.Add(OurFormStack.Peek())
End Sub
The AddForm method will show a form and add it to the stack. RemoveForm will do the reverse. In AddForm, first we check to ensure that the stack exists. That is probably unnecessary but I am being a little over-cautious. Then we clear what is currently in the User Control, so if the TopText is there then it will be cleared or any form will be cleared out. Then we push the new form onto our stack. Then we do a few things that are necessary for putting a form into the User Control; we remove the border, tell Windows that the form is not a top-level window and to not show it in the Task Bar. Then we make the form visible and set the "Dock" property to "Fill" so the form fills the User Control. Then we add the form to the controls in the User Control and the form is the only thing in the User Control.
You can now build that. You might have to build it because you need the User Control to be in the Toolbox. After building the project, go to Form1 and then look at the Toolbox. At the top of the Toolbox you should see our StackingControl. Drag it and drop it onto Form1. Set the Dock property to Fill.
Then create a Form2 and Form3. For each of them, just create a label saying what they are (such as "Form Two" and "Form Three") and a button. In the button click handler, just call "Close". You don't really have to have the button; you could close the forms just by clicking the "x" in the upper-right of the forms.
Then add a menu strip to Form1. Create menu items for "Form Two", "Form Three" and "Exit". For "Exit" just call "Close()". Use the following for the other two menu items:
Dim f As New Form2()
AddHandler f.FormClosed, AddressOf SubForm_FormClosed
StackingControl1.AddForm(f)
That is for Form2. Use the same for Form3 except change the number of course. Add following method:
Private Sub SubForm_FormClosed(sender As Object, e As FormClosedEventArgs) Handles MyBase.FormClosed
Dim c As Form = TryCast(sender, Form)
If c Is Nothing Then
MessageBox.Show("sender is not a Form")
Return
End If
Try
StackingControl1.RemoveForm(c)
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
End Class
Notice that the menu item click handlers both use the "SubForm_FormClosed" method; that is what "AddHandler f.FormClosed, AddressOf SubForm_FormClosed" does. It sets the FormClosed event handler for the form so that Form1 knows when the other form is closed; the other forms don't need anything extra for this to work. In the FormClosed event handler we first check to be sure that we are being called for a form (it is nearly certain we are) then we call StackingControl to remove the form. StackingControl will remove the form that is in it, pop off the next one and ensure (just to be sure) that it is the one that is expected, then it will either put the TopText label into itself or it will show the next form from the stack.

How to pass a value selected on an initial form to the main form?

I want to do something like the answer here:
How can I close a login form and show the main form without my application closing?
...but I want to pass a value selected on the initial form to the next (main) form. If I call an overridden constructor on the main form, where do I store the value in the meantime (between the initial form being dismissed and the main form being called)?
OTOH, if, instead of using the program.cs file to do this, I create the "initial form" inside the main form's Load() event (is there a better place), I could do something like this, but admittedly it seems rather kludgy:
0) Set the main form's size to 0,0 to hide it
1) Show the "initial" form/modal dialog, and store the value the user selects (in a button click event) in a form-global variable
2) Once the initial form/modal dialog closes, set the main form's size back to what it should be (unless modal result <> OK, in which case I close the main form and the app)
I know there's a better way to do this...
You don't have to pass a value to the main form. Just like your link explains, open your main form first. Then your main form can open the other form. This other form can place the information in a public property that the main form can access. Since the main form controls the lifetime of this other form, the main form gets the information held in the other form's public property, then closes the other form.
string myVariable;
using (OtherForm otherForm = new OtherForm())
{
otherForm.ShowDialog();
myVariable = otherForm.OtherVariable;
}
Try using ApplicationContext (System.Windows.Forms.ApplicationContext). You can show multiple forms as shown in the example in the following MSDN thread. And regarding data,you can have a common data object which is created once and the forms are instantiated with the data object passed to them before showing them.
http://msdn.microsoft.com/en-us/library/system.windows.forms.applicationcontext%28v=vs.100%29.aspx

Why calling Hide in a child form's FormClosing event handler hides the parent form?

When Form2 is closed, via it's X button, the Main form is sometimes hidden as well, but not always. Often times the Main form is hidden after initial 'newForm' button click and other times many open-close operations are required before the Main form gets hidden on Form2's closing. Why is this happening? Why is it irregular?
This is a small test code for a larger application I'm working on. In that application a thread continuously reads the network stream and when a particular message is encountered a modal form is displayed. The user can close that modal form or it can be told to close itself by a different network message. In this event, to give the user some time to view the data that the form is displaying I implemented a delayed form closing for that form. When the form is running its delay closing code, another message can come in over the network that will open up a new instance of this form in which case, I observed, that once the timer of the original form runs out, the original form is left displayed until the new instance is closed. Calling Hide in the FormClosing event handler closes the original form if more than one instances of it are running, but it has this side effect of hiding the entire application (the Main form) when the last instance of this form is closed, either by the user or by the delayed closing code. And again, the entire application is not always hidden, but it does happen.
//Main form's 'newForm' button
private void btn_newForm_Click(object sender, EventArgs e)
{
Form2 f = new Form2();
f.ShowDialog();
}
public partial class Form2 : Form
{
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
Hide();
}
}
Update (from the application I'm working on):
The problem is shown visually below. The top part of the picture, labeled "A", represents the situation where the first modal dialog (greyed out) was instantiated and it is in the process of being auto closed after 4 seconds have elapsed. The second instance (blue window heading) is active and awaiting input. In the lower part of the picture, labeled "B", the counter to closing of the first instance has completed, yet the first instance remains visible. Adding Hide does not change picture "A" but picture "B" would only be showing the active modal dialog, which is what I want. If Hide is not used and we have the case shown in "B", once the active modal dialog is closed the inactive dialog will disappear together with the active one, but no sooner. At this time my main form will be hidden as well, sometimes.
Your main form doesn't get hidden, it disappears behind another window. The flaw in your code is that for a brief moment none of your windows can get the focus. Your main window can't get the focus, it got disabled by your dialog and won't get re-enabled until the dialog is fully closed. Your dialog can't get the focus, you hide it. So Windows goes looking for another window to give the focus to and can only pick a window owned by another application. Like Visual Studio, nice and big so your main window is well covered by it.
Not sure what you are trying to do, it doesn't make sense to call Hide() since the dialog will close a couple of microseconds later. Just delete the statement.
I am not sure if I am right but maybe you forgot to add e.Cancel = true; to your closing event.
Second, I think using a modal form is only usefull when you expect an action like OK or CANCEL from user, that is where DialogResults comes handy. It sounds strange if this happens time to time not all the time! maybe you can try like this:
//Main form's 'newForm' button
//Define form in your mainform
private Form2 f;
private void btn_newForm_Click(object sender, EventArgs e)
{
if(f != null) { f.Show(); return; }
f = new Form2()
f.FormClosing += delegate { f.Hide(); };
f.Show();
}
I know the topic is quite old, but I recently had to look for answers for this precise question.
Why hiding the (child modal) form instead of closing it ?
I may be wrong, but I think that in some cases, hidding the modal child form instead of closing it is sometimes useful.
For example, I'm using a class that is a custom tree of grids. Think of something like an Excel Document with multiples tables (sheets) and each table can have child tables. A very powerful manner to store datas that can be used by multiple objects and multiple forms at a time.
Now, this "TreeTable_Class" object has an inbuilt custom form that actually shows the content of one of its tables at a time in a GridView, and you can select which table to show by selecting it in a Treeview. You can see here that the "Database Editor" is actually and MDI Form that can load the Form from any TreeTable_Class.
And this is the Form I use to edit the content of a Cell for a given (selected) Table (I've chosen another cell with long text content from another table in this database)
Now, when you choose to close the custom form instead of hiding it, that form will be unaccessible, you can't show it anymore, and you get an exception (no instance of the object) Somewhat, it isn't disposed yet (so the check If MyForm Is Nothing Then... is useless) I know I have to implement the GarbageCollector and dispose the Child Form manually, but it's outside the scope of this topic.
Anyway, my class could use a large amount of memory, of datas, and if I had to rebuilt ALL the contents each time I want to show a new instance of that form, that would be a large amount of workload in my application. That's why I have chosen to hide the form instead of closing it until the main application exits or when a specific CloseFormAndDispose() method is explicitly called, either by the program, or if I make this option available for the user via an user interface.
Workaround try :
This is the workaround I've found to override the "form replaced by another because none of the parent/child ones could be retrieved" :
Sorry, I'm in VB.. but you can use a tool to convert this to C#, or do it manually, it's pretty simple..
// This is the child, a Cell Editor that can edit the content of a Cell.
Protected WithEvents _CellEditor As CellEditor_Form = Nothing
This Editor form is a member of TreeTable_Form, a form that can actually show and edit the content of the whole Database File (a single file)
And this TreeTable_Form class contains a routine that handles CellEditor closing event
Public Partial Class TreeTable_Form
// Sorry. The "WithEvents" in C# is a litte bit complex to me... So, in VB :
Protected WithEvents _CellEditor As CellEditor_Form = Nothing
// ...
// CellEditor handling method (I used a Code converter...) :
// The original VB declaration is :
// Protected Sub RecallFormAfterCellEditorHidden() Handles _CellEditor.Closed
// You'll have to write specific Event handler for _CellEditor object declared above...
protected void RecallFocusAfterCellEditorHidden()
{
Application.DoEvents();
this.Focus();
}
End Class
This tiny protected void RecallFormAfterCellEditorHidden() method in your Class (if you are using a class that contains Forms) or in your Main From, assuming that your main form contains the child forms (dialogs) will try to force the focus on your Application or MainForm...
By the way, TreeTable_Form is actually a component of TreeTable_Class. The later is an object that can be used anywhere you want. In a Main Form Application, in another Class, in a dialog, anywhere... and could be passed by reference to share its contents between several items. And this TreeTable_Class contains a RecallFocusAfterTreeViewerHidden() method that handles the closing of that form. That means, the Form or Application that actually uses the class will get the focus each time you close the its child Form. I've made it that way to get an object that could be used anywhere
We still get problems !
However, this method will make your application flicker a bit each time you close your child dialog, and doesn't succeed at 100% ! Sometimes, my parent form still disappear from screen and gets struck behind another window. Alt+TAB wont helt either. But this happens less than without this method trick. I don't have any better answer at this time, still searching... I'll come back here if I find out how. I'm using this custom made application in my work to write memos during meetings for example, and produce PV (procès verbal - french sorry) in PDF or DOCx on the fly...
And I'm sorry, I'm in VB, not C#. Hope this helps a little, until we find a better workaround for this...

Form won't save after creating it with EnvDTE

I have created a Visual Studio Add-In that adds a form to an existing Project in the opened solution.
This is how I create the form:
string templatePath = sol.GetProjectItemTemplate("Form.zip", "csproj");
//sol is an EnvDTE80.Solution2
proj.ProjectItems.AddFromTemplate(templatePath, formName);
//proj is an EnvDTE.Project
After that I can successfully get the reference to the ProjectItem of the added form, then I can get a reference to the System.Windows.Forms.Form, and through this reference I can add a button to the form like this:
Button btn = new Button();
btn.Text = "my funky button";
btn.Name = "newButton";
btn.Size = new Size(150, 23);
btn.Location = new Point(30, 30);
frmNewForm.Controls.Add(btn);
//frmNewForm is a System.Windows.Forms.Form
And then the button is successfully added to the form:
However, when I try to save this form, it just won’t save. I click Visual Studio’s [save] button, it just doesn’t turn gray. Even if I click [Save All], the form won’t be saved. Then I close Visual Studio, reopen it, and open the project to which I have added the new form with my Add-In, and the new button simply isn’t there. Just an empty form.
I’ve even tried saving the project and the solution programmatically through the following code:
itemForm.Save(itemForm.Name);
//itemFrom is an EnvDTE.ProjectItem
proj.Save(proj.FullName);
//proj is an EnvDTE.Project
I’ve thought that this would be because the instance of the Visual Studio that I was using to test my Add-In is a debug one, opened right after I run my Add-In. But I’ve tried using the installed Add-In (which remained automatically after running it), and the problem persisted.
Update
I’ve just noticed two things:
1) the button only appears on the design of the form, and nowhere else. And it doesn’t even let me select it to see it’s attributes.
It’s name doesn’t appear in Intellisense, in the object list, or even on the design document of the form.
As a test, I’ve added a button manually, and this one I can select, and interact with it:
What I could get from that is that I am not adding the button properly.
Then the new question regarding the button would be: How can I add a new button to a form created through EnvDTE in a way that I can interact with it in design time ?
2) While trying to see the differences from my funky button and my Manually added button, I’ve attempted something I hadn’t before with a programmatically created form: instantiate and run it.
And here's how I've done it:
MyFunkyForm frm = new MyFunkyForm ();
frm.Show();
It flashes on the screen (apparently with none of my two buttons), and the execution ends. Even if I try to do something on it’s Form_load, it’s executed, then the form flashes, and the execution is ended (the form is closed and debugging is over), as if I had called the Close() method.
Then the additional question would be: Did I skip a step while adding the form, or am I not creating it properly at all ?
you are adding a form to a c# project, I think you should not instantiate the form alone by itself like you did but if you want to see it you should execute the application.
I don't know how to do this, never tried myself, found this, hopefully it's helpful:
http://www.mztools.com/articles/2006/mz2006016.aspx

Categories

Resources