If I create a class derived from System.Windows.Window and show it with ShowDialog it appears above the main window as expected, and the main window is disabled.
However it is possible to put both windows behind other applications, and then just bring the main window back. This just leaves a single window which appears to have crashed, and can be confusing.
Is it possible to ensure that the dialog window is always displayed if the main window is shown? The MessageBox.Show dialog has no such problems
Update:
A test dialog is defined as
public partial class MyDialog : Window
{
public MyDialog()
{
InitializeComponent();
}
}
and called using
MyDialog d = new MyDialog();
d.ShowDialog();
you have to set the Owner property.
MyDialog d = new MyDialog();
d.Owner = Application.Current.MainWindow;//or your owning window
d.ShowDialog();
To ensure that the dialog window is always displayed if the main window is shown, add handler to main form visibility changed event to set TopMost true or false to child form according to main visibility
ChildForm frmDLg = null;
public MainForm()
{
this.VisibleChanged += MainFrmVisibleChanged;
}
private void LoadDialogForm()
{
try {
if (frmDLg == null || frmDLg.IsDisposed) {
frmDLg = new ChildForm();
}
frmDLg.ShowDialog();
} catch (Exception ex) {
//Handle exception
}
}
private void MainFrmVisibleChanged(object sender, System.EventArgs e)
{
if (frmDLg != null && !frmDLg.IsDisposed) {
frmDLg.TopMost = this.Visible;
}
}
Update
public override bool Visible
{
get
{
return base.Text;
}
set
{
base.Text = value;
// Insert my code
if (frmDLg != null && !frmDLg.IsDisposed)
{
frmDLg.TopMost = this.Visible;
}
}
}
The last cure i can think is to use a timer with user32 dll getforegroundwindow to check if main form is visible.
This code should work as you want
public MainWindow()
{
InitializeComponent();
this.Activated += new EventHandler(MainWindow_Activated);
}
void MainWindow_Activated(object sender, EventArgs e)
{
if (m == null)
return;
m.Activate();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
m = new MyDialog();
m.ShowDialog();
}
MyDialog m;
Related
I have form to show Customer and vendors if I open form from button1 the forms Show customer and if I open from button 2 form show vendor
the problem here I wanna the buttons open form 1 time for each I made this code but the first it work for the first opened form only and the another button open many time as much as I click the button
if (Application.OpenForms[frm.Name] != null)
{
if (Application.OpenForms[frm.Name].Text == e.Item.Caption)
{
frm = Application.OpenForms[frm.Name];
frm.BringToFront();
}
else
{
frm.Show();
}
}
else
frm.Show();
Ok, here is the code for the form that contains the buttons. I just called it Form1.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnCustomer_Click(object sender, EventArgs e)
{
btnCustomer.Enabled = false;
CustomerVendorForm form = new CustomerVendorForm(btnCustomer);
form.Show();
}
private void btnVendor_Click(object sender, EventArgs e)
{
btnVendor.Enabled = false;
CustomerVendorForm form = new CustomerVendorForm(btnVendor);
form.Show();
}
And here is the CustomerVendor form:
public partial class CustomerVendorForm : Form
{
Button Form1Button;
public CustomerVendorForm(Button button)
{
InitializeComponent();
Form1Button = button;
}
private void CustomerVendorForm_FormClosed(object sender, FormClosedEventArgs e)
{
Form1Button.Enabled = true;
}
So we disable the button that they clicked. Open the form, passing the button. When the user closes the form, the button is re-enabled.
Does that make sense?
In your constructor:
btnVendor.Tag = new VendorForm();
btnCustomer.Tag = new CustomerForm();
In your button click handler (you only need one - this code will handle any number of different buttons and forms)
anyButton_Click(object sender, EventArgs e){
((sender as Control).Tag as Form).Visible ^= true;
}
--
So, your Tag is in use by some Thing already? OK, probably the easiest thing is to is make a class to hold all the things you want to put in the Tag:
class TagBucket{
public Form SomeForm { get; set; }
public Whatever OtherThing { get; set; } //you don't have to set this now, just demonstrating
}
In your constructor:
btnVendor.Tag = new TagBucket {
SomeForm = new VendorForm(),
OtherThing = new Whatever()
};
btnCustomer.Tag = new TagBucket {
SomeForm = new CustomerForm(),
OtherThing = new Whatever()
};
In your click handler:
anyButton_Click(object sender, EventArgs e){
((sender as Control).Tag as TagBucket).SomeForm.Visible ^= true;
}
well I modified my code to get open forms text and add them to string and checked if the string contain the caption of button it wont open it for second time
here is my code ,thanks for David.Warwick he give me the idea where i need to start
if (Application.OpenForms[frm.Name] != null)
{
var texts = "";
foreach (Form fr in Application.OpenForms)
{
texts += fr.Text + "/";
}
if (texts.Contains(e.Item.Caption.ToString()))
{
frm = Application.OpenForms.Cast<Form>().Where(x => x.Text == e.Item.Caption.ToString()).FirstOrDefault();;
frm.BringToFront();
}
else
{
frm.Show();
}
}
else
frm.Show();
I want display a window only one time. When the user click on this button:
private void Notification_Click(object sender, RoutedEventArgs e)
{
NotificationSettings notifications = new NotificationSettings();
notifications.ShowDialog();
}
this will create a new window, I want that if there is already a window opened the user can't open a new one. There is an option in xaml for tell to compiler this? I remember the vb.net with windows form that allow to set the option to show only one windows at time.
Thanks.
Just hold a reference to your window in a field/property and check if it's Visisble already.
well I am not sure what is NotificationSettings exactly but for a window you can create a bool flag to mark when the window is opened and closed, check this code:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
bool WindowFlag = false;
private void button_Click_1(object sender, RoutedEventArgs e)
{
Window TestWindows = new Window();
TestWindows.Closing += TestWindows_Closing;
if (WindowFlag == true)
{
MessageBox.Show("The Window is already opened");
}
else
{
TestWindows.Show();
WindowFlag = true;
}
}
private void TestWindows_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
WindowFlag = false;
}
}
I'm making an MDI App that Works like a text editor. I'm using a method that verifies that there is an MDI Children form existing to perform an "undo" action with HasChildren.
private void undoToolStripMenuItem_Click(object sender, EventArgs e)
{
if(this.HasChildren)
{
Console.WriteLine("Nobody said it was easy");
myForm newMyForm =(myForm)this.ActiveMdiChild;
newMyForm.Undo();
}
}
The problem is that HasChildren, after the execution of InitializeComponent() in the MDIForm is always true! I executed this code:
public myMDIParent()
{
Console.WriteLine(HasChildren);
InitializeComponent();
Console.WriteLine(HasChildren);
bool hasChildren =this.MdiChildren.Length==0;
Console.WriteLine(hasChildren);
}
And i get this output (i can't post images)
false
true
true
So, why HasChildren is true if there is no Children Forms?
You can try this way to check if the "undo" form existed.
myForm newMyForm;
private void undoToolStripMenuItem_Click(object sender, EventArgs e)
{
if(newMyForm == null)
{
newMyForm = new myForm();
newMyForm.MdiParent = this;
newMyForm.Show();
}
else
{
newMyForm.Activate();
newMyForm.Undo();
}
}
Luckily, you don't need to check HasChildren. Just look whether ActiveMdiChild is null:
private void undoToolStripMenuItem_Click(object sender, EventArgs e)
{
myForm newMyForm = ActiveMdiChild as myForm;
if (newMyForm != null) {
Console.WriteLine("Nobody said it was easy");
newMyForm.Undo();
}
}
I've got two forms, with subForm being called/created by a buttonClick in Form1. Right now I can initiate subForm, hide Form1, and then unhide Form1 when subForm is closed. What I'd like to be able to do is:
If user clicks changeform button, check to see if subForm is active but hidden
If no, then initiate subForm, else hide Form1, unhide subForm and pass control to it
If user clicks subForm's changeform button, hide subForm, unhide Form1 and pass control to it
If user clicks the "X" in the upper right corner of the form, then close the application, regardless of which form is active. (Right now, selecting the "X" closes the subForm and opens/unhides Form1.)
I can find solutions that do part of the requirements (and maybe all, I'm just too noob to know). To repeat from my previous question here, the code I have so far is:
Form1
private void countClick(object sender, EventArgs e)
{
this.Hide();
subForm myNewForm = new subForm();
myNewForm.ShowDialog();
this.Show();
countSelect.Checked = false;
}
and subForm
private void totalClick(object sender, EventArgs e)
{
this.Close();
}
This works, but it's not really elegant.
I think the best way to do this is to roll your own ApplicationContext. This allows you full control over the application lifetime without having it being tied to a specific Window. See http://msdn.microsoft.com/en-us/library/ms157901.aspx for more information.
Here's an example:
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MyApplicationContext());
}
}
public class MyApplicationContext : ApplicationContext
{
public MyApplicationContext()
{
ShowForm1();
}
public void ShowForm1()
{
if (_form2 != null)
_form2.Hide();
if (_form1 == null)
{
_form1 = new Form1(this);
_form1.FormClosed += OnFormClosed;
}
_form1.Show();
MainForm = _form1;
}
public void ShowForm2()
{
if (_form1 != null)
_form1.Hide();
if (_form2 == null)
{
_form2 = new Form2(this);
_form2.FormClosed += OnFormClosed;
}
_form2.Show();
MainForm = _form2;
}
private void OnFormClosed(object sender, FormClosedEventArgs e)
{
if (_form1 != null)
{
_form1.Dispose();
_form1 = null;
}
if (_form2 != null)
{
_form2.Dispose();
_form2 = null;
}
ExitThread();
}
private Form1 _form1;
private Form2 _form2;
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public Form1(MyApplicationContext context)
: this()
{
_context = context;
}
private void button1_Click(object sender, EventArgs e)
{
if (_context != null)
_context.ShowForm2();
}
private readonly MyApplicationContext _context;
}
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
public Form2(MyApplicationContext context)
: this()
{
_context = context;
}
private void button1_Click(object sender, EventArgs e)
{
if (_context != null)
_context.ShowForm1();
}
private readonly MyApplicationContext _context;
}
So we'll start out by going to the child form and creating a new event that can be used to notify the parent when it wants to change forms:
public event Action ChangeForm;
Then we fire the event and hide the child form when it wants to change forms:
private void ChangeForm_Click(object sender, EventArgs e)
{
Hide();
if (ChangeForm != null)
ChangeForm();
}
The parent form needs an instance of the child form as an instance field:
private subForm child = new subForm();
And it needs to initialize it in it's constructor, both adding handlers to the ChangeForm event to show the parent, and to the closed event to close itself:
public Form1()
{
InitializeComponent();
child.ChangeForm += () => Show();
child.FormClosed += (s, args) => Close();
}
Then all that's left is for the parent form to hide itself and show the child when it wants to change forms:
private void ChangeForm_Click(object sender, EventArgs e)
{
Hide();
child.Show();
}
Why not simply setting them to foreground, topmost, and so on ?
And setting them back vice versa ?
---added as comment as proposed
To access MainForm fromsubForm:
Create a constructor in your subForm and a field:
MainForm MainFormRef_Field;
subForm(MainForm MainFormRef)
{
this.MainFormRef_Field = MainFormRef;
}
Now you can access your MainForm using this reference. Like this:
MainFormRef_Field.Show();
MainFormRef_Field.Hide(); //or how ever you want to handle it
To access subForm fromMainForm:
To handle your subForm use the object you created for it. Here:
subForm myNewForm = new subForm();
To close whole application if any of the form closes:
Set a Form_Closing event for both forms:
private void MainForm_Closing(object sender, EventArgs e)
{
Application.Exit();
}
private void subForm_Closing(object sender, EventArgs e)
{
Application.Exit();
}
Note:
I am not writing the whole code for all of your cases. Set the variables, check the conditions. Its all up to you that how code it. All the main points you needed I've provided you the solution of them.
I'm trying to have the owner-form minimize when the modal-form is minimized. But when I minimize the modal-form – it disappears completely. (- I can click on the owner-form.)
How do I solve this?
I have:
public partial class Form1 : Form
{
Form2 frm2 = new Form2();
public Form1()
{
InitializeComponent();
frm2.Owner = this;
}
private void button1_Click(object sender, EventArgs e)
{
frm2.ShowDialog();
}
}
And:
class Form2 : Form
{
Form1 frm1;
FormWindowState ws = new FormWindowState();
public Form2()
{
SizeChanged += new EventHandler(Form2_SizeChanged);
}
void Form2_SizeChanged(object sender, EventArgs e)
{
frm1 = (Form1)Owner;
if (WindowState == FormWindowState.Minimized)
{
ws = frm1.WindowState;
frm1.WindowState = FormWindowState.Minimized;
}
else frm1.WindowState = ws;
}
}
(While trying this, I also ran into this: Modal form doesn't appear in tray until minimized and owner-form is clicked once. How do I make it appear? )
This is by design. As part of the modality contract, showing a dialog disables all the other windows in the application. When the user minimizes the dialog window, there are no windows left that the user can access. Making the app unusable. Winforms ensures this cannot happen by automatically closing the dialog when it gets minimized.
Clearly you'll want to prevent this from happening at all. Set the MinimizeBox property to false. The MaximizeBox property ought to be set to false as well, making both buttons disappear from the window caption. Leaving room for the HelpButton btw.
I don't recall every needing this much code to get modal Windows to work. I'm concerned by your comment 'I can click on the owner form', which leads me to believe that the form is nt being correctly set up as modal. By defintion, modal forms must be dealt with before user control can return to the owner form. Minimizinfg the modal form does not constitute properly 'dealing' with the modal form.
Here is some code that I have used in the past. Notes: passing the owner as parameter in ShowDialog establishes the ownership relationship. While I suspect your code works, I've not used it that way.
Also, when I have done this, I have not put any special code in the modal form, and have also disabled all the button in the upper right corner of the form; thereby insuring that the user cannot close, minimize, or maximize the modal form outside of any buttons I have provided.
public partial class Form1 : Form
{
Form2 frm2 = new Form2();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
frm2.ShowDialog(this);
}
}
I hope this helps.
Forms have a property ShowInTaskbar. If it is set to false then the form will never appear on the task bar, even when minimized.
Add a:
Show();
At the end of Form2's event-handler.
I also had the requirement where when minimizing a dialog form it should minimize the application and when restoring the application it should show the dialog again. Here's what I did:
MainForm.cs
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2.Show(this, "Testing 123");
}
}
Form2.cs
public partial class Form2 : Form
{
bool isMinimized;
private Form2()
{
InitializeComponent();
ShowInTaskbar = false;
}
private void Form2_FormClosed(object sender, FormClosedEventArgs e)
{
if (Owner != null)
{
Owner.Enabled = true;
}
}
private void Form2_Load(object sender, EventArgs e)
{
MinimizeBox = Owner != null;
if (Owner != null)
{
Owner.Enabled = false;
}
}
private void Form2_SizeChanged(object sender, EventArgs e)
{
if (Owner != null)
{
if (WindowState == FormWindowState.Minimized && Owner.WindowState != FormWindowState.Minimized)
{
Owner.Enabled = true;
Owner.WindowState = FormWindowState.Minimized;
isMinimized = true;
}
else if (isMinimized && Owner.WindowState != FormWindowState.Minimized)
{
Owner.Enabled = false;
}
}
}
public static void Show(Form owner, string message)
{
var form2 = new Form2();
form2.label1.Text = message;
if (owner != null)
form2.Show(owner);
else
form2.ShowDialog();
}
}