I have a form with a button in it. If i click the button another form opens. If I return to the parent form with the help of tab and click the same button again it does nothing.
Here is my code:
private void pictureBox1_Click(object sender, EventArgs e)
{
form wadd = new form(this);
if ((IsFormAlreadyOpen(typeof(form))) == null)
{
wadd.MdiParent = Form1.ActiveForm;
wadd.Show();
}
}
public static Form IsFormAlreadyOpen(Type FormType)
{
foreach (Form OpenForm in Application.OpenForms)
{
if (OpenForm.GetType() == FormType)
return OpenForm;
}
return null;
}
private void Form1_MdiChildActivate(object sender, EventArgs e)
{
if (this.ActiveMdiChild == null)
tabForms.Visible = false;
// If no any child form, hide tabControl
else
{
this.ActiveMdiChild.WindowState = FormWindowState.Maximized;
// Child form always maximized
// If child form is new and no has tabPage,
// create new tabPage
if (this.ActiveMdiChild.Tag == null)
{
// Add a tabPage to tabControl with child
// form caption
TabPage tp = new TabPage(this.ActiveMdiChild.Text);
tp.Tag = this.ActiveMdiChild;
tp.Parent = tabForms;
tabForms.SelectedTab = tp;
this.ActiveMdiChild.Tag = tp;
this.ActiveMdiChild.FormClosed += new FormClosedEventHandler(ActiveMdiChild_FormClosed);
}
else
{
tab();
}
if (!tabForms.Visible) tabForms.Visible = true;
}
}
public void tab()
{
for (int i = 0; i < tabForms.TabCount; i++)
{
if (tabForms.TabPages[i].Text == this.ActiveMdiChild.Text.ToString())
{
tabForms.SelectedTab = tabForms.TabPages[i];
break;
}
}
}
private void ActiveMdiChild_FormClosed(object sender, FormClosedEventArgs e)
{
//Destroy the corresponding Tabpage when closing MDI child form
if (tabForms.HasChildren)
{
((sender as Form).Tag as TabPage).Dispose();
}
//If no Tabpage left
else if (!tabForms.HasChildren)
{
tabForms.Visible = false;
}
}
private void tabForms_SelectedIndexChanged(object sender, EventArgs e)
{
if ((tabForms.SelectedTab != null) && (tabForms.SelectedTab.Tag != null))
(tabForms.SelectedTab.Tag as Form).Select();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (!tabForms.HasChildren)
{
Application.Exit();
}
}
The result I want is when I click the button again the tab should gets focused to this form rather than opening new form which is not permissable.
I think you'd want something like this:
public Form FormOpened<T>()
{
foreach (Form form in Application.OpenForms)
if (typeof(T) == form.GetType())
return form;
return null;
}
You could then use it like this:
form f = (form)FormOpened<form>();
if (f2 == null)
{
f2 = new form();
f2.MdiParent = this;
f2.Show();
}
else
{
f2.Focus();
}
Tell me if you need any help.
You want something like this I believe:
form wadd;
private void pictureBox1_Click(object sender, EventArgs e)
{
if (wadd == null)
{
wadd = new form(this);
}
wadd.MdiParent = Form1.ActiveForm;
wadd.Show();
}
You just have the logic backwards. If there is no form open, then create it then open it. If there is a form already then just use it.
Related
I have a button on Form1 that opens Form2(Leaderboard) if Form2 is not open. What I am trying to do is: On Button click, if Form2 is closed, open Form2. Else Form2 is open, bring Form2 to front.
With the below code, clicking the button when leaderboardOpen == true; does nothing at all.
public static bool leaderboardOpen = false;
private void leaderButton_Click(object sender, EventArgs e)
{
if (leaderboardOpen == false)
{
Leaderboard leaderboard = new Leaderboard();
leaderboard.Show();
leaderboardOpen = true;
}
else
{
Leaderboard leaderboard = new Leaderboard();
//Tried the below
//leaderboard.Focus();
//leaderboard.BringToFront();
//leaderboard.TopMost = true;
//leaderboard.Activate();
}
}
Instead of a bool, keep a reference to your instance of Leaderboard itself:
private Leaderboard leader = null;
private void leaderButton_Click(object sender, EventArgs e)
{
if (leader == null || leader.IsDisposed)
{
leader = new Leaderboard();
leader.FormClosed += (s2, e2) => { leader = null; };
leader.Show();
}
else
{
if (leader.WindowState == FormWindowState.Minimized)
{
leader.WindowState = FormWindowState.Normal;
}
leader.BringToFront();
}
}
Got it working with the below code.
private void leaderButton_Click(object sender, EventArgs e)
{
var form = Application.OpenForms.OfType<Leaderboard>().FirstOrDefault();
if (form != null)
{
form.Activate();
}
else
{
new Leaderboard().Show();
}
}
Here is a working code for me
public static bool leaderboardOpen = false;
public static Leaderboard? leaderboardForm = null;
private void leaderButton_Click(object sender, EventArgs e)
{
if (!leaderboardOpened || leaderboardForm is null)
{
// Initialize Leaderboard form if it doesn't exist
leaderboardForm = new Leaderboard();
leaderboardForm.Show();
leaderboardOpened = true;
}
else
{
// Focus on the form
leaderboardForm.Focus();
}
}
Make sure to make leaderboardOpened = false; if the Leaderboard form is closed.
I have this method(below) that works well First time it's called:
public void showForm(Form _form, Form _main)
{
if (_main != null)
{
foreach (Form otherForms in this.MdiChildren)
{
otherForms.Close();
}
}
_form.MdiParent = this;
_form.Dock = DockStyle.Fill;
_form.TopLevel = false;
_form.TopMost = true;
_form.FormBorderStyle = FormBorderStyle.None;
this.MDIChildPanel.Controls.Add(_form);
_form.BringToFront();
_form.Show();
}
on Form_Load event for MDI Parent Form i call the method above as shown below and it works well:
private void MDIRental_Load(object sender, EventArgs e)
{
showForm(new Login(), null);
}
I then try to call the method above from another event handler and it just doesnt work as show below: help
private void manageUsersToolStripMenuItem_Click(object sender, EventArgs e)
{
showForm(new Users(), null);
}
I have two windows forms in my application. First one is Main form and the second one is lookup form. I'm trying to open lookup form from the main form in a text box key leave event and then I'm opening the lookup form. My lookup form has a data grid view and I' loading it in the form load event of the lookup form. I'm reading my selected value on the grid view of the lookup window to an object. I want to close the lookup window as soon as I read the values of the selected row to the object and I want to pass it to the main form? How can I do that?
This is what I have done.
In the main form.
LookupModelType="";
if (e.KeyCode.Equals(Keys.F3))
{
foreach (Form frm in Application.OpenForms)
{
if (frm is FormControllers.Lookup)
{
if (frm.WindowState == FormWindowState.Minimized)
{
frm.WindowState = FormWindowState.Normal;
frm.Focus();
return;
}
}
}
LookupModelType = "Product";
FormControllers.Lookup newLookUp = new FormControllers.Lookup(LookupModelType);
newLookUp.ShowDialog(this);
}
In the lookup window
private string GridType = "";
public Lookup(String LookupModelType)
{
InitializeComponent();
this.GridType = LookupModelType;
}
private void Lookup_Load(object sender, EventArgs e)
{
if (GridType == "Product")
{
using(DataControllers.RIT_Allocation_Entities RAEntity = new DataControllers.RIT_Allocation_Entities())
{
dgvLookup.DataSource = RAEntity.TBLM_PRODUCT.ToList<DataControllers.TBLM_PRODUCT>();
}
}
dgvLookup.ReadOnly = true;
}
private void dgvLookup_CellClick(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex < 0)
{
return;
}
int index = e.RowIndex;
dgvLookup.Rows[index].Selected = true;
}
you can do it like blow :
in the Main form :
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.F3)
{
LookupForm look = new LookupForm();
var result = look.ShowDialog();
if(result == DialogResult.OK)
{
MessageBox.Show(look.data.ToString());
}
}
}
and in the look up form you have to declare 1 variable and fill whenever cell clicked
public partial class LookupForm : Form
{
public object data = new object();
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
data = dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value;
this.DialogResult = DialogResult.OK;
this.Close();
}
}
of course, for better performance, you can declare the variable in specific type
To share data between Parent Child forms using events, here are the things needed:
A public custom event args class to share data.
Child form to have a event.
In your parent form whenever you create an instance of child, you
need to register eventhandlers
Please note that the code below is just a demo code and you will need to add null checks etc. to make it "robust".
Custom event args below
public class ValueSelectedEventArgs : EventArgs
{
public object Value { get; set; }
}
Your lookup form should have the following event declared:
public event EventHandler ValueSelected;
protected virtual void OnValueSelected(ValueSelectedEventArgs e)
{
EventHandler handler = ValueSelected;
if (handler != null)
{
handler(this, e);
}
// if you are using recent version of c# you can simplyfy the code to ValueSelected?.Invoke(this, e);
}
In my case I am firing the event on listbox selected index change and closing the form as well. Code for it:
private void checkedListBox1_SelectedIndexChanged(object sender, EventArgs e)
{
var i = this.checkedListBox1.SelectedIndex;
ValueSelectedEventArgs args = new ValueSelectedEventArgs();
args.Value = i;
OnValueSelected(args);
this.Close();
}
Finally in the parent form you have to register for the eventhandler
private void textBox1_Leave(object sender, EventArgs e)
{
lookup myLookup = new lookup();
myLookup.ValueSelected += MyLookup_ValueSelected;
myLookup.Show();
}
private void MyLookup_ValueSelected(object sender, EventArgs e)
{
textBox2.Text = (e as ValueSelectedEventArgs).Value.ToString();
}
I personal like to add dynamically the lookup window, and I do something like this:
//examble object
class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
// the value which you want to get from datagridview
private Person _selectedValue;
// the datagridview datasource, which you neet to set
private IEnumerable<Person> _gridDataSource =
new List<Person>()
{
new Person {FirstName="Bob",LastName="Smith" },
new Person {FirstName="Joe",LastName="Doe"}
};
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if(e.KeyCode== Keys.F3)
{
var btnOk = new Button() { Text = "Ok", Anchor= AnchorStyles.None };
var btnCancel = new Button() { Text = "Cancel",Anchor= AnchorStyles.Right };
var dg = new DataGridView();
var bs = new BindingSource();
bs.DataSource = _gridDataSource;
dg.DataSource = bs;
dg.Dock = DockStyle.Fill;
dg.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
//setup a layout wich will nicely fit to the window
var layout = new TableLayoutPanel();
layout.Controls.Add(dg, 0, 0);
layout.SetColumnSpan(dg, 2);
layout.Controls.Add(btnCancel, 0, 1);
layout.Controls.Add(btnOk, 1, 1);
layout.RowStyles.Add(new RowStyle(SizeType.Percent));
layout.RowStyles.Add(new RowStyle(SizeType.AutoSize));
layout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent));
layout.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
layout.Dock = DockStyle.Fill;
//create a new window and add the cotnrols
var window = new Form();
window.StartPosition = FormStartPosition.CenterScreen;
window.Controls.Add(layout);
// set the ok and cancel buttons of the window
window.AcceptButton = btnOk;
window.CancelButton = btnCancel;
btnOk.Click += (s, ev) => { window.DialogResult = DialogResult.OK; };
btnCancel.Click += (s, ev) => { window.DialogResult = DialogResult.Cancel; };
//here we show the window as a dialog
if (window.ShowDialog() == DialogResult.OK)
{
_selectedValue =(Person) bs.Current;
MessageBox.Show(_selectedValue.FirstName);
}
}
}
I have a List view inside a user control, that user control placed inside MDI form, now what i have to do is i have to populate the list view based on the MDI menu click. i tried the below method but its not working, the method getting triggered but the list view not getting update. Here is my sample code
User control
public ucQuickLaunch()
{
InitializeComponent();
ListFill("Loaded..");
}
public void ListFill(string Message)
{
try
{
ListViewItem myitem = new ListViewItem();
myitem.Text = DateTime.Now.ToLongTimeString().ToString();
myitem.SubItems.Add(Message);
ListViewStatus.Items.Add(myitem);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
MDI Menu click
public ucQuickLaunch objQuickLaunch=new ucQuickLaunch();
private void newToolStripMenuItem_Click(object sender, EventArgs e)
{
FrmGeneral frm = new FrmGeneral();
FrmGeneral open = Application.OpenForms["FrmGeneral"] as FrmGeneral;
if (open == null)
{
frm.MdiParent = this;
frm.Show();
objQuickLaunch.ListFill("General button clicked");
}
else
{
open.Activate();
if (open.WindowState == FormWindowState.Minimized)
{
open.WindowState = FormWindowState.Normal;
}
}
}
I assume you have your custom control (ucQuickLaunch ) placed on your form (FrmGeneral). If so you need to add method for filling that control to your form:
public partial class FrmGeneral : Form
{
public FrmGeneral()
{
InitializeComponent();
}
public void ListFill(string value)
{
objQuickLaunch.ListFill(value);
}
}
and your menu:
private void newToolStripMenuItem_Click(object sender, EventArgs e)
{
FrmGeneral open = Application.OpenForms["FrmGeneral"] as FrmGeneral;
if (open == null)
{
FrmGeneral frm = new FrmGeneral();
frm.MdiParent = this;
frm.ListFill("General button clicked");
frm.Show();
}
else
{
open.Activate();
if (open.WindowState == FormWindowState.Minimized)
{
open.WindowState = FormWindowState.Normal;
}
}
}
what is this error :
Form that was specified to be the MdiParent for this form is not an MdiContainer.
Parameter name: value
here is the code
public partial class Form5 : Form
{
public Form5()
{
InitializeComponent();
}
private void Form1_MdiChildActivate(object sender, EventArgs e)
{
if (this.ActiveMdiChild == null)
tabForms.Visible = false; // If no any child form, hide tabControl
else
{
this.ActiveMdiChild.WindowState = FormWindowState.Maximized; // Child form always maximized
// If child form is new and no has tabPage, create new tabPage
if (this.ActiveMdiChild.Tag == null)
{
// Add a tabPage to tabControl with child form caption
TabPage tp = new TabPage(this.ActiveMdiChild.Text);
tp.Tag = this.ActiveMdiChild;
tp.Parent = tabForms;
tabForms.SelectedTab = tp;
this.ActiveMdiChild.Tag = tp;
this.ActiveMdiChild.FormClosed += new FormClosedEventHandler(ActiveMdiChild_FormClosed);
}
if (!tabForms.Visible) tabForms.Visible = true;
}
}
// If child form closed, remove tabPage
private void ActiveMdiChild_FormClosed(object sender, FormClosedEventArgs e)
{
((sender as Form).Tag as TabPage).Dispose();
}
private void tabForms_SelectedIndexChanged(object sender, EventArgs e)
{
if ((tabForms.SelectedTab != null) && (tabForms.SelectedTab.Tag != null))
(tabForms.SelectedTab.Tag as Form).Select();
}
private void projectsToolStripMenuItem_Click(object sender, EventArgs e)
{
Form7 f7 = new Form7();
f7.MdiParent = this;
f7.Show();
}
}
The problem is probably that in your Form5 class you are not specifying that the Form is a MdiContainer.
Try setting the IsMdiContainer property to true or set the property manualy after you call InitializeComponent in the constructor.