I need to change a menuStrip item text of the main window (mdi container) from a child window,
something like this:
File
-Login
to
File
-Logout
On the main window add these:
public static MainForm Current;
public string FileLogin
{
get { return fileLoginToolStripMenuItem.Text; }
set { fileLoginToolStripMenuItem.Text = value; }
}
Obviously use the name that you set or was automatically set for the menu strip item for the login/logout menu item. then in the form constructor of the main form, set the Current.
public MainForm()
{
InitializeComponent();
Current = this;
}
Then from the other window/form you can call (to set the value):
MainForm.Current.FileLogin = "Logout";
But better than this is that you on your child window make an event,
public event Action UserLoggedIn = delegate { };
And on the MainForm have the MainForm subscribe to that event with a reverse of the above...
ChildForm.Current.UserLoggedIn += () => FileLogin = "Logout";
And have the child raise the event when the user logs in, with UserLoggedIn().
You can add to your MDI container a public method callable from any of its children.
Let's assume that this method is called SetLoggedStatus
(in MDI container)
public void SetLoggedStatus(bool status)
{
ToolStripMenuItem loginMenu = MenuStrip1.Items(0) as ToolStripMenuItem:
loginMenu.DropDownItems[0].Text = (status == true ? "Logout" : "Login");
}
Now we need to call this public method from the MDI Child form.
Every MDIChild form has a property that points back to the MDIParent
We can use that property casting the generic form instance to the correct MDI parent
(in MDIChild after login and supposing the MDIParent is a form class named MyParentForm)
MyParentForm f = this.MDIParent as MyParentForm;
if(f != null)
f.SetLoggedStatus(true);
This is how you can access main menu items from an MDI Child:
// this button in the child form
private void button1_Click(object sender, EventArgs e) {
ToolStripMenuItem tsm;
// file menu
tsm = (ToolStripMenuItem)this.MdiParent.MainMenuStrip.Items[0];
MessageBox.Show( tsm.DropDownItems[0].Name);
// first menu under File Menu
tsm.DropDownItems[0].BackColor = Color.Red;
// second menu under File Menu
tsm.DropDownItems[1].BackColor = Color.Wheat;
}
You can change the font or text same way; instead of back color you can use .text.
Related
First of all, I want to apologize for:
The software is in Portuguese.
The software is ugly as hell. It is for a school project and we decided to focus more on the funcionality than the design (I know, it's wrong, but we had to choose...)
I read update combobox from another form in c# but I didn't understand what happened.
That said, let's go to the issue.
I have this window:
If I click the button marked in red:
This will open:
This is supposed to be a software for a market. The first window is responsible to order more thing to the inventory. The second window is responsible to add a supplier into the system.
The combobox shows all the suppliers on the system. I want when I finish adding a supplier on the second window after I clicked on the button highlighted with the red rectangle, the combobox will update automatically with the new data.
I used a "Update" button with this code:
this.tb_FornecedorTableAdapter.Fill(this.tccDataSet.tb_Fornecedor);
It worked, but I tried to use on FormClosing, FormClosed and Deactivate events on the other windows and it didn't work at all (I modified the "this" on the code to a lot of this and it didn't help me). Is there a way to do what I want?
If the ComboBox is updated with the data from SQL Server then you can try this:
// When button Adicionar is clicked
private void buttonAdd_Click(object sender, EventArgs e)
{
using(Form formAdd = new Form()) // This is the Gerenciar Fornecedor form
{
formAdd.ShowDialog(this); // Show the form. The next statement will not be executed until formAdd is closed
// Put the your code to update the ComboBox items here
}
}
In the first window declare a public methord:
public void RefreshCombo()
{
this.tb_FornecedorTableAdapter.Fill(this.tccDataSet.tb_Fornecedor);
}
Then in the first window add button click event
WindowB window=new WindowB(this);
WindowB.Show();
Then in the child window add a ctor method:
private WindowA windowParent;
public WindowB(WindowA parent)
{
InitializeComponent();
this.windowParent=parent;
}
In WindowB FormClosing Event
this.windowParent.RefreshCombo()
What you can do in this case is to add a property on the child form to store the combo box value and populate it when the combo box value changes. Also, create a method on the child form that will be called from the parent form. It will show the child form and return the combo box value.
public partial class ChildForm : Form
{
public ChildForm()
{
InitializeComponent();
}
private string _comboValue { get; set; }
public string ShowAndGetComboValue()
{
this.ShowDialog();
return _comboValue;
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
_comboValue = comboBox1.SelectedItem.ToString();
}
}
On the parent form, you can then display the child form this way:
ChildForm form = new ChildForm();
string comboValue = form.ShowAndGetComboValue();
I've the following problem:
My program (Winforms) has a main window with a treeView control.
When the user selects a node in the treeView a new child window shall be created.
This works just fine.
But the problem is, that after this child window has become visible, the main window comes to front and partially hides this child window.
I've build a little mockup in order to make sure that it is not only related to my program:
namespace FatherAndSon
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Son aNewSon = new Son();
aNewSon.Visible = true;
}
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
Son aNewSon = new Son();
aNewSon.Visible = true;
}
}
}
When I press the button1, all is fine but when I select a node in the treeView, the main window jumps to the front immediately after the child form appeared.
What is wrong?
Change Visible = true to .Show(this) -> this change will make that child window will always be on top of it's Parent (main window in this case).
Son aNewSon = new Son();
aNewSon.Show(this);
if it is not acceptable that child form is always on top of it's parent then change it to:
Son aNewSon = new Son();
aNewSon.Visible = true;
aNewSon.Focus();
To have "aNewSon" always on top, you can also try to add the "TopMost" property to the newly created form:
aNewSon.TopMost = true;
Check Msdn about TopMost property.
Add the parent form to the constructor try use "Show" method instead of visible=true.
Son aNewSon = new Son();
aNewSon.Show(this);
may be, than you can also call BringToFront method Application.OpenForms["Form1"].BringToFront();
in your case:
Son aNewSon = new Son();
aNewSon.Show(this);
aNewSon.BringToFront();
I'm trying to change a text on a TextBox on a modal main form by clicking on a button from an another active form, need help.
Main form *Modal mode
public void changetext(){
textbox1.text = textnew;
}
form2 *active form
private void btnChange_Click(object sender, EventArgs e)
{
mainform form1 = new mainform;
public String textnew = "NEW"
form1.changetext();
this.close
}
Ive tired to use this code but it gives me the error of : Invoke or BeginInvoke cannot be called on a control until the window handle has been created.:
public void LabelWrite(string value)
{
if (InvokeRequired)
Invoke(new LabelWriteDelegate(LabelWrite), value);
else
{
textBox1.Text = value;
}
}
delegate void LabelWriteDelegate(string value);
i think there's a logic issue. If i understand your requirement, you have a main form which contains a search textbox. When the user launch a serach, you open a modal form where all possible results are displayed. The user selects the value he wants and then you get the result in the main form. Is this correct? If so you should do it this way:
Create a public property on the modal form which contains the result.
Either create a public property or create a new constructor on the modal form to pass the query.
On the main form, you can access the public properties of the modal form as long as it is not disposed.
For instance:
var result = null;
var modal = new ModalForm(query);
if(modal.ShowDialog() == DialogResult.OK) // This means the user has selected a value
{
result = modal.SelectedResult;
}
modal.Close();
modal.Dispose();
The easiest way is to pass the new text to the modal window.
For example:
Main form Modal mode
public void changetext(String textnew){
textbox1.text = textnew;
}
form2 active form
private void btnChange_Click(object sender, EventArgs e)
{
mainform form1 = new mainform;
form1.changetext("NEW");
this.close
}
If I were you I would also change form names, they are a little bit confusing.
P.S. I still don't get what is this.close is needed for.
How can I close an opened window when I call a new window? That means I want only 1 child window at the time. I don't allow multi-window.
public partial class Main_Usr : Form
{
public Main_Usr()
{
InitializeComponent();
this.IsMdiContainer = true;
if (Program.IsFA) barSubItem_Ordre.Visibility = DevExpress.XtraBars.BarItemVisibility.Never;
Ordre_Liste f = new Ordre_Liste();
f.MdiParent = this;
f.Show();
}
private void barButtonItem_CreateOrdre_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
{
Program.AllerRetour = "Ordre Aller";
Ordre_Fiche f = new Ordre_Fiche();
f.MdiParent = this;
f.Show();
}
private void barButtonItem_OrdreListe_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
{
Ordre_Liste f = new Ordre_Liste();
f.MdiParent = this;
f.Show();
}
private void barButtonItem_CreateOrdRet_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
{
Program.AllerRetour = "Ordre Retour";
Ordre_Fiche f = new Ordre_Fiche();
f.MdiParent = this;
f.Show();
}
}
There are different ways to implement pseudo masterpage:
You can create BaseForm form with desired layout. Then inherit other forms from this BaseForm and provide custom content.
You can create MainForm form with desired layout. Then create content controls as UserControls and show them in panel.
You can create MasterUserControl with desired layout. Then create content controls by inheriting from MasterUserControl (they will have same layout). Then use your main form as browser for displaying different content controls like pages.
EXAMPLE:
Create desired layout on Main_Usr form.
Do not set it as MdiContainer
If you want to access some controls (e.g. footer or header from child forms, set property Modifiers of those controls to protected)
Open Ordre_Liste form code and change it to inherit from Main_Usr form, instead of Form
Add custom content to Ordre_Liste form
voila! you have 'masterpage'
UPDATE (for 3rd option)
Create new user control with name MasterUserControl
Create desired layout on this control, keeping space for custom content (btw don't use TableLayoutPanels - they have issue with designer inheritance).
Create new user control with name HomeUserControl and change it to inherit from your MasterUserControl.
Open HomeUserControl designer and add custom content. Also you can modify parent controls, which has protected modifier.
On your main form place HomePageUserControl
There different ways to implement navigation between controls (aka pages). Simplest way - have menu on main form. Other way - define event 'Navigate' on master control, subscribe to that event on main form, and raise it from 'pages'.
Create Form instances on a class level.
Then you can access to them from events or methods.
Form1 f1;
Form2 f2;
void OpenForm1()
{
f1 = new Form1()
f1.Show();
}
void OpenForm2()
{
f1.Dispose(); //or Hide if you want to show it again later
f2 = new Form2();
f2.Show();
}
Like:
List<Form> openForms = new List<Form>();
foreach (Form f in Application.OpenForms)
openForms.Add(f);
foreach (Form f in openForms)
{
if (f.Name != "Menu")
f.Close();
}
Note, do NOT close them directly, becuase there will come to an error, if you would try to close (or dispose) them in the 1st foreach loop. Thats why you need to put them into a list and close them there.
I am using visual studio 2010 to do my C# GUI.
The current problem that I am facing is that after maximizing a window, it stays there but when I go to other forms, the window will go back to its original size.
How do I leave the maximized window all the way for all the forms, once I click the maximize button?
Heres an example:
User maximizes Form A
Form A maximized
User goes to Form B
Form B goes back to original size instead of a maximized window
What I want is when user maximizes a form, it stays that way till the program is closed or resized.
Assuming you're using WinForms, you can have either implement a shared FormWindowState manager or use a Multiple Document Interface (MDI) container.
Shared FormWindowState
You can register each of your forms with a class responsible for propagating changes in forms' FormWindowState.
public class FormWindowStateManager {
List<Form> _Forms;
...
public void Register(Form form) {
if(!_Forms.Contains(form)) {
_Forms.Add(form);
form.Resize += new EventHandler(Form_Resize);
}
}
public void Unregister(Form form) {
if(_Forms.Contains(form)) {
_Forms.Remove(form);
form.Resize -= new EventHandler(Form_Resize);
}
}
private void Form_Resize(object sender, EventArgs e) {
Form form = sender as Form;
if(form != null) {
if(form.FormWindowState == FormWindowState.Maximized || form.FormWindowState == FormWindowState.Normal) {
PropagateWindowState(form.FormWindowState);
}
}
}
private void PropagateWindowState(FormWindowState state) {
foreach(Form form in _Forms) {
if(form.FormWindowState != state) {
form.FormWindowState = state;
}
}
}
}
MDI Container
MdiParentForm.cs
IsMdiContainer = true;
MdiChildForm.cs
MdiParent = myParentForm; // instance of MdiParentForm
You can iterate through a form's MDI children using the form's MdiChildren property such that when on MDI child window changes its FormWindowState, the MDI parent form can apply the change to each of its children, similar to the shared FormWindowState approach.
These ideas are just off the top of my head but maybe they'll get you in the right direction.