I've been trying so hard to show the tab pages, actually hide the tab pages is working but show i tried everything but nothing successfully here's the code:
this is how i call the form that the user puts his password:
private void adminToolStripMenuItem1_Click(object sender, EventArgs e)
{
Password pss = new Password();
pss.Show();
}
this is the button that have to add the Tab-Page:
private void btnGo_Click(object sender, EventArgs e)
{
if(String.IsNullOrWhiteSpace(txtGo.Text))
{
lblErro.Text = "Type the password.";
return;
}
if(txtGo.Text != Properties.Settings.Default.Pass)
{
lblErro.Text = "Incorrect password.";
return;
}
else
{
this.Close();
MainForm main = new MainForm();
main.operatorToolStripMenuItem1.Checked = false;
main.adminToolStripMenuItem1.Checked = true;
main.accountPermissionsAdm();
}
}
this is the function i created to the account permissions when the user is admin:
public void accountPermissionsAdm()
{
if (!settings)
tabControl_Config.TabPages.Add(tabPage_Report);
if (!pathLoss)
tabControl_Config.TabPages.Add(tabPage_PathLoss);
if (!instrument)
tabControl_Config.TabPages.Add(tabPage_Instrument);
if (!parameters)
mainTabControl.TabPages.Add(tabPage_DefineParameters);
if (!scenario)
mainTabControl.TabPages.Add(tabPage_RunScenario);
if (!customer)
mainTabControl.TabPages.Add(tabPage_CustomerId);
IntPtr h = this.tabControl_Config.Handle;
tabControl_Config.TabPages.Insert(3, tabPage_RunCondition);
}
UPDATE - after reading your edited question with more code:
Few potential problems:
In btnGo_Click you are calling this.Close(); which returns, so the rest of the code in this else statement is unreachable.
Even if you will not call this.Close();, the code has no practical meaning, as you are creating a new instance of MainForm but you didn't show it (either by calling main.Show() or main.ShowDialog()).
Not sure if that's the flow, but it looks like Password is a child of your main form (MainForm). If that's the case, you should change the behavior so that, for example (there are other approaches) Password will return some value (boolean for example) that the main form needs to be changed (insertion of TabPage etc.). The change then must be performed on the main form and not from other forms.
Please follow these guidelines and make the changes, or consider of a new design, as it seems very broken to me.
Original answer (how to hide/show tab page)
I'm afraid you can't hide TabPage. You will have to remove and add it again. For example, like this:
Hide:
this.tabControl1.TabPages.Remove(tabPage1);
Show:
this.tabControl1.TabPages.Add(tabPage1);
The reason is that the Hide() function will have no effect in this situation, according to MSDN:
TabPage controls are constrained by their container, so some of the
properties inherited from the Control base class will have no effect,
including Top, Height, Left, Width, Show, and Hide.
Related
I am working on a WinForms Desktop application in C# .NET. The target framework is .NET Framework 4.8. When the application is started, the main form is displayed with several buttons. Each button hides the main form when clicked and opens another form that displays data with which the user interacts. The main form is the owner of the new form.One button opens a form that presents a list of files from a network share folder in a data grid view. The user selects a row in the data grid and clicks a button to import the information in the file to various tables in a SQL Server database. When the import is complete, the selected row is removed from the data grid. When the user closes this form, there is code in the Form Closed event to show the owner. This all works well.My problem is that when the main form is unhidden, I need to disable the button that opens the form to list files to import if there are not any files in the network share folder to be imported. There is also a line of code to change the button's text property informing the user there are not any files to import.I realize I can place the code to disable the button and change button text in the VisibleChanged event. But, I only want the code to run after the owned form's closed event shows the owner form. How do I enclose the code in the main form's VisibleChanged event to disable the file import button only after the owned form is closed. Or, is it possible to edit the properties of the button on the owner form in the Form Closed event prior to the Owner.Show();I found a similar question WinForm Form Closed Event. But when I follow the suggestion
private void LoadChildForm_Click(object sender, EventArgs e)
{
ChildForm form = new ChildForm();
form.FormClosed += new FormClosedEventHandler(ChildFormClosed);
form.Show();
}
substituting my names
private void btnImportHFR_Click(object sender, EventArgs e)
{
Form form = new frmHFRFiles();
form.FormClosed += new FormClosedEventHandler(frmHFRFiles_FormClosed);
form.Show(this);
Hide();
}
Visual Studio flags frmHFRFiles_FormClosed as an error for the name does not exist in the current context.
ChildForm form = new ChildForm(this);
Then in ChildForm constructor:
MainForm m_MainForm;
Public ChildForm (MainForm mainForm)
{
m_MainForm = mainForm;
}
Then in closing event:
m_MainForm.button1.Enabled = false;
Ensure button1 is public
Here is what I did. I created a boolean variable in the main form and set the initial value to false.
private bool updateButtons = false;
The main form's constructor executes the search for files in the network folder.
public frmMainMenu()
{
InitializeComponent();
Shared.FilesForImport = GetHFRFiles();
}
The form's load event calls the EnableButtons() method
public void EnableButtons()
{
btnImportHFR.Enabled = Convert.ToBoolean(Shared.FilesForImport.Count);
btnImportHFR.Text = btnImportHFR.Enabled ? "Find Available HFR" : "No HFR For Import";
btnGetFacilityStatus.Enabled = Shared.sqlWrap.GetDataForFacStat(Shared.DsFacStat);
updateButtons = false;
}
The main form's visible changed event fires after the form load event. The network folder is not searched again because the updateButtons value is set to false.
private void frmMainMenu_VisibleChanged(object sender, EventArgs e)
{
if(updateButtons)
{
EnableButtons();
}
}
In the button click event, the updateButtons value is set to true after the main form is hidden.
private void btnImportHFR_Click(object sender, EventArgs e)
{
frmHFRFiles form = new frmHFRFiles();
form.Show(this);
Hide();
updateButtons = true;
}
The child form's closed event calls the Owner.Show() method
private void frmHFRFiles_FormClosed(object sender, FormClosedEventArgs e)
{
Owner.Show();
}
This causes the main form's visible changed event to fire. Only this time the EnableButtons() method will run because the updateButtons value is true.
private void frmMainMenu_VisibleChanged(object sender, EventArgs e)
{
if(updateButtons)
{
EnableButtons();
}
}
public void EnableButtons()
{
btnImportHFR.Enabled = Convert.ToBoolean(Shared.FilesForImport.Count);
btnImportHFR.Text = btnImportHFR.Enabled ? "Find Available HFR" : "No HFR For Import";
btnGetFacilityStatus.Enabled = Shared.sqlWrap.GetDataForFacStat(Shared.DsFacStat);
updateButtons = false;
}
Finally, the EnableButtons() method sets the updateButtons value to false.
It seems rudimentary to me, but it works. Thank you everyone for your feedback.
My problem is that when the main form is unhidden, I need to disable the button that opens the form to list files to import if there are not any files in the network share folder to be imported. There is also a line of code to change the button's text property informing the user there are not any files to import.
So your main form has a button X. If this button is clicked a method is called. This method will first hide the form, then show the subform until the subform is closed. The method should disable button X, change the button's text and unhide the form.
To make this flexible, we won't do everything in one procedure, we make several procedures with the intention of the procedure: "Inform operator there are no files to import" "Disable opening the subform", and of course their counterparts "Enable opening the subform", "Inform operator there are files to import"
TODO: invent proper method names
private void ShowNoFilesToImport()
{
this.buttonX.Text = ...;
}
private void DisableOpeningSubForm()
{
this.buttonX.Text.Enabled = false;
}
The advantage of this, is that if you later want to change the way that you want to inform the operator, for instance if you want to use an information field at the bottom of you screen, you will only have to change this in one place.
Furthermore, you can reuse the procedures, for instance you can add a menu item that will do the same as button X, this menu item can call the same methods
private void PerformActionsButtonX() // TODO: invent proper name
{
// Hide this form, and show the Subform until it is closed
this.Visible = false;
using (var dlg = new SubForm())
{
// if needed, set properties of the subForm:
dlg.Text = ...
dlg.Position = ...
// show the form until it is closed
var dlgResult = dlg.ShowDialog();
this.ProcessDlgResult(dlgResult, dlg);
}
// Show that there are no files to Import and disable OpeningSubform
this.ShowNoFilesToImport();
this.DisableOpeningSubform();
// Finally: show this form:
this.Visible = true;
}
And of course call this method when ButtonX or menu item Y are clicked:
private void OnButtonX_Clicked(object sender, ...)
{
this.PerformActionsButtonX();
}
private void OnMenyItemYClicked(object sender, ...)
{
this.PerformActionsButtonX();
}
Hi I'm relatively new to C# and completely new to windows form and basically trying to create a subliminal messaging program that at timed intervals will quickly display a message for it to then be hidden again.
I've managed to by looking through various other posts created another form that will pop up and then hide very quickly using
msgObject.Activate();
that brings the form to the front. However it is stopping me from being able to type when I'm working and I basically wanting to know if it is possible to make some kind of message or form appear at the front of all my other programs without it interrupting my current work or opening or closing of other windows and tasks if that makes sense. As currently it brings the form to the front of everything but will also stop me from being able to type etc.
I'm not sure if this is possible with my current method of using a form but if there is a way of achieving the result I'm after I'd be very grateful to find out
Thanks.
Here is more of my code to clarify
public partial class FormHomePage : Form
{
private bool startSubliminal = false;
msg msgObject = new msg();
List<string> subliminalMessages = new List<string>();
public FormHomePage()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void timer1_Tick(object sender, EventArgs e)
{
if (startSubliminal)
{
msgObject.Show();
msgObject.BringToFront();
msgObject.Activate();
}
}
private void button1_Click(object sender, EventArgs e)
{
subliminalMessages.Add(txtBox1.Text);
msgObject.LabelText = txtBox1.Text;
txtBox1.Text = string.Empty;
startSubliminal = true;
msgObject.Show();
msgObject.BringToFront();
}
private void timer2_Tick(object sender, EventArgs e)
{
msgObject.Hide();
}
}
How are you showing the second form (the message form) in the first place? You're probably using .Show() (right?), which will make the form "steal" the focus anyway. The same applies to .Activate() and .BringToFront().
Instead, what you can do is to show the message form and make sure it stays on top the current form, and then activate the current/main form once again.
Something like this should work:
var frm = new YourMsgForm();
frm.Show(this);
this.Activate();
Here's a demonstration:
Note that I used .Show(this) instead of .Show(), that's in order to set the current form as the Owner of the new one, that way we guarantee that the new form will stay on top of the current one. This is equivalent to calling frm.Owner = this; then frm.Show();.
Another way to make sure the form stays on top is by setting the TopMost property instead of the Owner property. However, doing so will make the new form on top of the other windows as well (not just your application).
I apologize if this has been addressed already, but I could not find a case that fit my exact situation. So here goes...
I have a MainForm that contains a toolStrip1 docked to the left that functions as a vertical navigation bar. I have a panel (pnlMain) filling up the remainder of the form. I want to use pnlMain to display different forms which are made up of win form classes. Right now, I can click on the labels/buttons on toolStrip1 to display different forms within pnlMain.
private void tsLblCustomers_Click(object sender, EventArgs e)
{
hidePanels();
CustomerReport cr = new CustomerReport();
cr.TopLevel = false;
cr.AutoScroll = true;
cr.BackColor = Color.White;
pnlMain.Controls.Add(cr);
cr.Show();
}
What I want to do now is display additional forms within pnlMain by clicking on a button on another form rather than a label/button on toolStrip1. Some of my forms are as follows: CustomerReport, AddCustomer, EmployeeReport, AddEmployee. The Report forms are linked to my tool strip buttons. The Add forms are linked to buttons on the Reports forms. I tried several things including the following:
1) On CustomerReport, I tried creating an instance of MainForm, then I'll create an instance of AddCustomer, and then add that instance to the panel on MainForm.
2) I also tried creating a method in MainForm to create the instance of AddCustomer, and then call that method from the Add button on CustomerReport. Even though the code was the same as the toolstrip buttons on MainForm, it did not work.
I tried different variations of hiding forms, showing forms, clearing the panel, setting Visible to true or false, and I can't get it to work right. In some cases, I've managed to hide the CustomerReport, but AddCustomer will not come up. At some point I think I created a NEW instance of MainForm and my code wasn't impacting the original form that is already open. I'm just lost. Should I be using a different design? Originally I set up my application to just hide one form then show the other but I read that that is a 'terrible design'.
This sounds very similar to this thread here: Creating Form Inside the Form
You'd want to look into MDI.
Although it sounds like you're aiming for one cohesive interactive window. Otherwise, if you just want separate windows to popup, you can create properties within that other form and read them after returning a DialogResult. I'm not sure why this would be bad design without knowing more about the context of the program.
//Optionally do a hide(); here.
AddCustomer customer = new AddCustomer();
DialogResult result = customer.ShowDialog();
if(result == DialogResult.OK)
{
var name = customer.Name;
//More properties or whatever here.
}
//The properties would still be accessible here, too.
I ended up keeping the toolstrip nav bar on the left side of the primary window, and I created a panel in the main part of the window. All forms are displayed in the panel. Each time one of the label options in the nav bar is clicked on, the current form is cleared off the panel and the active form is displayed.
private void tsLblCustomers_Click(object sender, EventArgs e)
{
pnlMain.Controls.Clear();
CustomerReport cr = new CustomerReport();
cr.TopLevel = false;
cr.AutoScroll = true;
cr.BackColor = Color.White;
pnlMain.Controls.Add(cr);
cr.Show();
}
private void tsLblEmployees_Click(object sender, EventArgs e)
{
pnlMain.Controls.Clear();
EmployeeReport emp = new EmployeeReport();
emp.TopLevel = false;
emp.AutoScroll = true;
emp.BackColor = Color.White;
pnlMain.Controls.Add(emp);
emp.Show();
}
private void tsLblVendors_Click(object sender, EventArgs e)
{
pnlMain.Controls.Clear();
VendorReport vend = new VendorReport();
vend.TopLevel = false;
vend.AutoScroll = true;
vend.BackColor = Color.White;
pnlMain.Controls.Add(vend);
vend.Show();
}
private void MainForm_Load(object sender, EventArgs e)
{
WelcomeForm welcome = new WelcomeForm();
welcome.TopLevel = false;
welcome.AutoScroll = true;
welcome.BackColor = Color.White;
pnlMain.Controls.Add(welcome);
welcome.Show();
}
This may seem totally unreasonable to ask, but I have been designing a multi-panel, real device simulator, that has many different screens and my current approach is to add all the screen objects from the code only and dispose them when I switch to another screen.
I have some fixed objects, that are the real device buttons that are already defined and in place. The thing is, I am separating each panel construction in methods, for example: buildLogin(), buildMainScreen(), etc, and I need to edit some of the screen objects from those methods, like changing the color of an enabled function label to green if enabled or white if disabled.
My question is: would it be possible to declare an object from a method that would be accessible in the whole class, like if it were defined in the variable declaration section? It would be something like the GLOBAL in PHP.
I can't declare it on top of everything like they would always be because when I dispose the objects, I can't "re-create" them, because of parenting, or re-using a disposed object or something...
[EDIT] Sample code:
public partial class frmMain : Form
{
//I could as well do this:
//Button button1 = new Button();
public frmMain()
{
buildLogin();
}
private void buildLogin()
{
Panel panel1 = new Panel();
Controls.Add(panel1);
//But then, there is no way to do this:
// if (button1.IsDisposed == true) //because of the panel, or smthing
Button button1 = new Button();
panel1.Controls.Add(button1);
button1.Click += (s, f) => { panel1.Dispose(); buildMainMenu(); };
}
private void buildMainMenu()
{
Panel panel2 = new Panel();
Controls.Add(panel2);
Button button2 = new Button();
panel2.Controls.Add(button2);
}
//This was created from the Designer and is class-scoped
private void btn_Frame_TSK1_Click(object sender, EventArgs e)
{
//Here, I have no access to the objets I've created programatically.
//button1.Text = "Text changed!";
}
}
If you want to make sure things are always completely dynamic and always done in the code behind, you may want to look at searching for the controls you've created in the Controls collection.
For example, make sure to give button1 an ID value (button1.ID="textUpdatedButton") that will identify it uniquely from other controls you create. Then use FindControl or search on the Controls collection to find the control with the ID you want to locate in your event handler.
//This was created from the Designer and is class-scoped
private void btn_Frame_TSK1_Click(object sender, EventArgs e)
{
Control control = this.FindControl("textUpdatedButton");
if(control != null && control is Button){
Button button1 = (Button)control;
button1.Text = "Text changed!";
}
}
Alternatively, to make things look more like a variable, you can use a Property to hide the control finding (as mentioned previously):
private Button Button1 {
get { return (Button)this.FindControl("textUpdatedButton"); }
}
//This was created from the Designer and is class-scoped
private void btn_Frame_TSK1_Click(object sender, EventArgs e)
{
if(this.Button1 != null){
this.Button1.Text = "Text changed!";
}
}
The actual implementation will vary with how you build up your controls, but essentially this approach can let you build everything dynamically in your code behind if you need to do it that way. Just remember to use identifiers to let you find things later.
Define your object at the class level, as Static. This way it will be accessible from all methods of all instances of the class(disposing an instance will not affect it).
I have a countdown Timer form - on the first form the user will enter the countdown time - warning times, end message, etc. There are also two Radio buttons (Max/Min) and depending on which is selected they will open a new Max or Min form where the time will actually start to countdown. It is working fine and counting down as I expect. However, if I exit the Max or Min form and try to run again with new times I get the error. The code is below - note the comment out ShowDialog(this); was something I tried - it let me close and open the new forms ok but it did not actually start the countdown. UpdateLabels is the function that does the updating of Labels.
bool Max = rbMax.Checked;
if (Max == true)
{
//_Max.ShowDialog(this);
_Max.Show();
}
else
//_Min.ShowDialog(this);
_Min.Show();
UpdateLabels();
}
I also tried the following which I read online as a possible solution but it also did not work...
private void Max_FormClosing(object sender, FormClosingEventArgs e)
{
this.Hide();
this.Parent = null;
}
Can anyone help me out - I can post the UpdateLabels function if needed. I am pretty new to UI C# development so any help would be great. Thanks.
The problem is, that a closed form can not be used anymore (be reopened). Thats why the code you posted tries to stop closing and only hides your window. But for doing this, the Cancel-property must be set to true:
private void Max_FormClosing(object sender, FormClosingEventArgs e) {
this.Hide();
this.Parent = null;
e.Cancel=true;
}
To show the form after closing it this way, show it with the Show() method.
However this is probably only a workaround and you could solve the problem with another design.
Maybe it would be wise, to create a new instance of your form, every time you need it, instead of trying to reopen it every time. This also has the advantage that the form only requesires resources if it is really needed.
What you can do is add a following check before calling .Show method:
if(_Max == null || _Max.IsDisposed)
_Max = new MaxForm();
_Max.Show();
and similarly for _Min form
Whenever a form is closed, all its resources are freed. This means that you can't access the object any more, since it no longer exists - it's been freed and deleted from memory. To prevent that, you can cancel the closing of the form, and hide it instead (which will appear transparent to the user).
this.Hide();
e.Cancel=true;
An updated version of your code is as follows:
private void Max_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = true;
this.Hide();
this.Parent = null;
}
The solution is simple that instantiate the object of the called form in the button click event e.g.
private void buttonSetting_Click( object sender, EventArgs e )
{
***_setting = new SettingWindow();*** //When I need to show the settings window
_setting.Show();
}
create new instatnce if object is not available
if(frmRGB==nullptr || frmRGB.IsDisposed==true )
{
frmRGB= new Form();
}
Create Object inside button click event
like this
private void btn_supplier_order_Click(object sender, EventArgs e)
{
form_supplier_order so = new form_supplier_order();
so.Show();
}