I have a button that opens a Window.
If the button is pressed again, it opens a duplicate of the same window.
info = new Info();
info.Owner = Window.GetWindow(this);
info.Show();
How do you check if the Window is already open, and deny a duplicate from being opened again?
I can't use info.ShowDialog() because it disables the Main Window.
Solutions that have not worked:
Info info = new Info();
if (!info.IsActive)
{
info = new Info();
info.Owner = Window.GetWindow(this);
info.Show();
}
Info info = new Info();
if (info.Visibility != Visibility.Visible)
{
info.Owner = Window.GetWindow(this);
info.Show();
}
public static bool IsWindowOpen<T>(string name = "") where T : Window
{
return string.IsNullOrEmpty(name)
? Application.Current.Windows.OfType<T>().Any()
: Application.Current.Windows.OfType<T>().Any(w => w.Name.Equals(name));
}
private void buttonInfo_Click(object sender, RoutedEventArgs e)
{
if (!IsWindowOpen<Window>("Info"))
{
Info info = new Info();
info.Owner = Window.GetWindow(this);
info.Show();
}
}
Create a form only when value is not null.
If the form was closed put the value back to null with the FormClosed event.
public static Info info;
if(info == null){
info = new Info();
info.Show();
}
put an event form close on the info form
private void info_FormClosed(object sender, FormClosedEventArgs e)
{
MainForm1.info = null;
}
It works for me
The sensible approach is to just keep track of the Window instance so you don't have to find it back later. Add a field:
private Info infoWindow;
If it is null then you know that the window doesn't exist yet, so you'll want to create it. Use the Closed event to set the variable back to null. If it is not null then you want to make sure that the window gets restored. So:
private void button_Click(object sender, RoutedEventArgs e) {
if (infoWindow == null) {
infoWindow = new Info();
infoWindow.Closed += (s, ea) => infoWindow = null;
infoWindow.Owner = this; // optional
infoWindow.Show();
}
else {
if (infoWindow.WindowState == WindowState.Minimized) {
infoWindow.WindowState = WindowState.Normal;
}
infoWindow.Activate();
}
}
And you probably also want to close the window automatically when the window that contains the button is closed:
private void Window_Closed(object sender, EventArgs e) {
if (infoWindow != null) infoWindow.Close();
}
You could use .IsLoaded field or bind the .ContentRendered event
Edit 1 -
Window1:
public class Window1 : Window
{
private Info info = null;
private Boolean IsInfoOpened = false;
protected void OpenInfo()
{
if (this.IsInfoOpened) return;
this.info = new Info();
this.info.ContentRendered += delegate { this.IsInfoOpened = true; };
this.info.Closed += delegate { this.IsInfoOpened = false; }
this.info.Show();
}
}
Related
Within my application i am trying to use forms in tabpages. These forms are all data managing forms.
I edited the tabcontrol (created a custom tabcontrol) so i can remove tabpages by double clicking on the tabheader.
protected override void OnMouseDoubleClick(MouseEventArgs e)
{
base.OnMouseDoubleClick(e);
//* Default method of closing a tab.
if (Selectedtab != null)
TabPages.Remove(Selectedtab);
}
Although it works. Its actually not doing what I need.
Because any changes on the form in the tabpage, are lost, regardless of the below
public partial class SomeForm : Form
{
private void SomeForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (HasChanges() && CustomMessage.WarningBox("There is unsaved data. Are you sure you want to close"))
return;
((TabControl)((TabPage)this.Parent).Parent).TabPages.Remove((TabPage)this.Parent);
}
}
When setting a breakpoint at this function, it never enters.
Now my question: Is it possible to call the Close method of the form from Tabcontrol. Preferably something like below.
protected override void OnMouseDoubleClick(MouseEventArgs e)
{
base.OnMouseDoubleClick(e);
if (Selectedtab != null)
{
if (Selectedtab.EmbeddedForm != null)
TabPages.ASelectedtab.EmbeddedForm.Close();
}
}
The main problem I am facing is I don't know how to access a function on a form from only knowing the selected tab. And I cant find it either.
Solution after using KyleWangs answer as base:
Custom Control:
protected override void OnMouseDoubleClick(MouseEventArgs e)
{
base.OnMouseDoubleClick(e);
string frmSearchName = "Frm" + SelectedTab.Name.Substring(3);
Form f = (Form)Application.OpenForms[frmSearchName];
if (f != null)
f.Close();
else
TabPages.Remove(SelectedTab);
}
Form:
private void SomeForm_FormClosing(object sender, FormClosingEventArgs e)
{
SetChanges();
if (HasChanges() && !CustomMessage.WarningBox("There is unsaved data. Are you sure you want to close?"))
e.Cancel = true;
else
((TabControl)((TabPage)this.Parent).Parent).TabPages.Remove((TabPage)this.Parent);
}
You can use property Application.OpenForms to get the open form instance.
private void Form1_Load(object sender, EventArgs e)
{
tabControl1.TabPages.Clear();
PageForm1 f1 = new PageForm1();
AddNewTab(f1);
}
private void AddNewTab(Form frm)
{
TabPage tab = new TabPage(frm.Text);
frm.TopLevel = false;
frm.Parent = tab;
frm.Visible = true;
tabControl1.TabPages.Add(tab);
frm.Location = new Point((tab.Width - frm.Width) / 2, (tab.Height - frm.Height) / 2);
tabControl1.SelectedTab = tab;
}
private void tabControl1_DoubleClick(object sender, EventArgs e)
{
Form f = (Form)Application.OpenForms[tabControl1.SelectedTab.Text];
f.Close();
tabControl1.TabPages.RemoveAt(tabControl1.SelectedIndex);
}
I need a hyperlink with target='_blank' from geckowebbrowser1 to open in geckowebbrowser2 and not in a new window.
private void geckowebbrowser1_CreateWindow(object sender, GeckoCreateWindowEventArgs e)
{
geckowebbrowser2.Navigate(e.Uri);
}
but a new window is created anyway :(
Looking at the source code, you could avoid creation of the new window by setting Cancel to false, like this:
private void geckowebbrowser1_CreateWindow(object sender, GeckoCreateWindowEventArgs e)
{
e.Cancel = true;
geckowebbrowser2.Navigate(e.Uri);
}
If you're interested, here's the part of the source code that handles the creation of a new window and calling the CreateWindow event handler:
GeckoWebBrowser browser = parent as GeckoWebBrowser;
if (browser != null)
{
var e = new GeckoCreateWindowEventArgs(flags);
browser.OnCreateWindow(e);
if (e.Cancel)
{
cancel = true;
return null; // When you set cancel to true on your end, the below code for creating a new window won't run
}
if (e.WebBrowser != null)
{
// set flags
((nsIWebBrowserChrome) e.WebBrowser).SetChromeFlagsAttribute(chromeFlags);
return e.WebBrowser;
}
nsIXULWindow xulChild = AppShellService.CreateTopLevelWindow(null, null, chromeFlags, e.InitialWidth, e.InitialHeight);
return Xpcom.QueryInterface<nsIWebBrowserChrome>(xulChild);
}
return null;
I get the default path from the registry for the Steam installation. But if someone has their games installed to a different folder, the user has to enter it in the Configure form. When the form gets closed, that path entered(from the folder browser or by typing the path in manually) should get saved to a string in the main form and should enable a different Combobox which turns on different buttons. I somehow managed to do the save to the mainform string, but the 2nd combobox doesn't seem to turn on. How can I do it correctly?
** MAIN FORM **
public string NewPath { get; set; }
private ConfigForm otherForm;
string InstallPath = (string)Registry.GetValue(#"HKEY_CURRENT_USER\SOFTWARE\Valve\Steam", "SteamPath", null);
private void PortalHammerButton_Click(object sender, EventArgs e)
{
Process.Start(InstallPath + #"\SteamApps\common\Portal\bin\hammer.exe");
}
private void Gamedropdown_SelectedIndexChanged(object sender, EventArgs e)
{
if (Gamedropdown.Text == "Portal") // When Portal is selected
{
// Enable the Portal SDK buttons
PortalHammerButton.Visible = true;
PortalModelViewerButton.Visible = true;
PortalFacePoserButton.Visible = true;
// Disable the CS:GO SDK buttons
csgoFacePoserButton.Visible = false;
csgoHammerButton.Visible = false;
csgoModelViewerButton.Visible = false;
}
else if (Gamedropdown.Text == "CS:GO") // When CS:GO is selected
{
// Disable Portal SDK buttons
PortalHammerButton.Visible = false;
PortalModelViewerButton.Visible = false;
PortalFacePoserButton.Visible = false;
// Enable CS:GO SDK buttons
csgoFacePoserButton.Visible = true;
csgoHammerButton.Visible = true;
csgoModelViewerButton.Visible = true;
}
}
private void ConfigureButton_Click(object sender, EventArgs e)
{
var configdialog = new ConfigForm();
configdialog.Show();
}
private void PortalDifferentHammerButton_Click(object sender, EventArgs e)
{
Process.Start(NewPath + #"\SteamApps\common\Portal\bin\hammer.exe");
}
private void NewDropDown_SelectedIndexChanged(object sender, EventArgs e)
{
if (NewDropDown.Text == "Portal") // When Portal is selected
{
// Enable the Portal SDK buttons
PortalDifferentHammerButton.Visible = true;
PortalDifferentModelViewerButton.Visible = true;
PortalDifferentFacePoserButton.Visible = true;
// Disable the CS:GO SDK buttons
DifferentCSGOFaceposerButton.Visible = false;
DifferentCSGOHammerButton.Visible = false;
DifferentCSGOModelViewerButton.Visible = false;
}
else if (NewDropDown.Text == "CS:GO") // When CS:GO is selected
{
// Disable the Portal SDK buttons
PortalDifferentFacePoserButton.Visible = false;
PortalDifferentHammerButton.Visible = false;
PortalDifferentModelViewerButton.Visible = false;
// Enable the CS:GO SDK buttons
DifferentCSGOModelViewerButton.Visible = true;
DifferentCSGOHammerButton.Visible = true;
DifferentCSGOFaceposerButton.Visible = true;
}
}
private void button1_Click(object sender, EventArgs e)
{
this.Close();
ConfigForm cfgfrm = new ConfigForm();
cfgfrm.Close();
}
}
}
**CONFIGURE FORM**
public partial class ConfigForm : Form
{
public ConfigForm()
{
InitializeComponent();
Form1 frm1 = new Form1();
frm1.NewPath = NewPathBox.Text;
}
public void DifferentFolderBrowseButton_Click(object sender, EventArgs e)
{
FolderBrowserDialog fbd = new FolderBrowserDialog();
DialogResult result = fbd.ShowDialog();
string newpath = fbd.SelectedPath;
NewPathBox.Text = newpath;
Form1 frm1 = new Form1();
frm1.NewPath = NewPathBox.Text;
}
public void CloseButton_Click(object sender, EventArgs e)
{
this.Hide();
Form1 frm1 = new Form1();
frm1.Gamedropdown.Visible = false;
frm1.NewDropDown.Visible = true;
}
}
}
Any help would be appriciated.
Look at your ConfigForm. Here's your problem:
public ConfigForm()
{
InitializeComponent();
Form1 frm1 = new Form1();
frm1.NewPath = NewPathBox.Text;
}
What you're doing on your Form1 (which I'm guessing is your Main form) is creating a new instance of your ConfigForm and showing it. What you're doing in your ConfigForm is creating a new main form and setting the NewPath = to the value entered on your config form. The problem is this new Form1 is NOT the Form1 that created the ConfigForm. The Form1 that created your config form is not the one getting updated by your code, some arbitrary new Form1 that you create is the one getting updated. This is why your code isn't working as you expected.
Here's the approach I would take. Add a NewPath variable to your ConfigForm just like you have in Form1. Then, add a FormClosing method to FormConfig. Do something like this:
private void ConfigForm_FormClosing(object sender, FormClosingEventArgs e)
{
NewPath = NewPathBox.Text;
}
Then, change your code on Form1 to this:
private void button1_Click(object sender, EventArgs e)
{
ConfigForm cfgfrm = new ConfigForm();
cfgfrm.ShowDialog();
this.NewPath = cfgfrm.NewPath;
}
What this code is doing is creating and showing a new ConfigForm on your Form1 when you click button1. Then, when your user closes the FormConfig, the form saves the textbox value to the NewPath variable on the FormConfig. Then, once the form is closed, the code on Form1 resumes. Form1 then looks at the NewPath value that was saved when the user closed the FormConfig. Form1 grabs this new NewPath value and puts it in its own NewPath variable.
EDIT
To show/hide comboboxes:
private void button1_Click(object sender, EventArgs e)
{
ConfigForm cfgfrm = new ConfigForm();
cfgfrm.ShowDialog();
this.NewPath = cfgfrm.NewPath;
Gamedropdown.Visible = false;
NewDropDown.Visible = true
}
I'm not sure why you are making the secondary form so complicated. You don't need a pointer to it after you use it and you should be closing instead of hiding. Try this:
class ConfigForm : Form
{
public string newPath = null;
public void CloseButton_Click(object sender, EventArgs e)
{
newPath = NewPathBox.Text;
}
public void CloseButton_Click(object sender, EventArgs e)
{
Close();
}
}
...and in your main form:
public partial class Form1 : Form
{
string steamPath = null; // set to starting path
private void ConfigureButton_Click(object sender, EventArgs e)
{
bool valueChanged = false;
using (ConfigForm form = new ConfigForm())
{
form.newPath = null;
form.ShowDialog();
if (form.newPath != null)
{
steamPath = form.newPath;
valueChanged = true;
}
}
if (valueChanged)
{
// here is where you would handle reloading and changing the ComboBoxes
}
}
}
This will more cleanly return the new string. Whatever you want to do as a result of having changed the path can be done after you have disposed of the config form (bringing it up with the "using" conditional automatically does the disposal for you)
I have a user control (AddNewTransaction) inside a Popup (NewTransaction in DebtPage.xaml) that I open with this code:
[DebtPage.xaml.cs]
public void Button_Click_1(object sender, RoutedEventArgs e)
{
if (!NewTransaction.IsOpen) { NewTransaction.IsOpen = true; }
NewTransaction.HorizontalOffset = (Window.Current.Bounds.Width) / 2 - (New_Transaction_Grid.Width / 2);
NewTransaction.VerticalOffset = (Window.Current.Bounds.Height) / 2 - (New_Transaction_Grid.Height / 2);
NewTransaction.Visibility = Visibility.Visible;
RetanguloBranco_Background.Visibility = Visibility.Visible;
}
The Popup opens and there's a custom control (AddNewTransaction) with a "Save" button. The button suppose to save data AND close the Popup. But it just save, the Popup keeps opened.
[AddNewTransaction.xaml.cs]
private static DebtPage _debtPage;
public static DebtPage debtPage
{
get
{
if (_debtPage == null)
{
_debtPage = new DebtPage();
}
return _debtPage;
}
}
private void BotaoSave_Click(object sender, RoutedEventArgs e)
{
SalvarTransaction(); //It's working!
debtPage.ClosePopup_NewTransaction(); //It is not!
}
[DebtPage.xaml.cs]
public void ClosePopup_NewTransaction()
{
NewTransaction.IsOpen = false;
NewTransaction.Visibility = Visibility.Collapsed;
RetanguloBranco_Background.Visibility = Visibility.Collapsed;
}
Thanks!
I've solved the problem with this:
private void BotaoSave_Click(object sender, RoutedEventArgs e)
{
SalvarTransaction();
Grid gridParent = this.Parent as Grid;
Popup parent = gridParent.Parent as Popup;
if (parent != null)
{
parent.IsOpen = false;
}
}
But I still want to know why ClosePopup_NewTransaction(); does nothing.
I have a form and I want to get an instance of the same form as stated in the code below. And I have a button: every time I press this button, if a new form is created, I want it to focus to that window, if not, I want to create a new form.
I managed to create a new form but if I want to focus on it, the code did not work, any ideas?
private void btn_Click(object sender, EventArgs e)
{
if (opened == false)
{
Text = "form1";
var form = new myformapp();
form.Show();
opened = true;
form.Text = "form2";
}
else
{
if (Application.OpenForms[1].Focused)
{
Application.OpenForms[0].BringToFront();
Application.OpenForms[0].Focus();
}
if (Application.OpenForms[0].Focused)
{
Application.OpenForms[1].BringToFront();
Application.OpenForms[1].Focus();
}
}
}
You can try shortening your code without the need to introduce more variables with this example:
void button1_Click(object sender, EventArgs e) {
bool found = false;
for (int i = 0; i < Application.OpenForms.Count; ++i) {
if (Application.OpenForms[i].GetType() == typeof(myformapp) &&
Application.OpenForms[i] != this) {
Application.OpenForms[i].Select();
found = true;
}
}
if (!found) {
myformapp form = new myformapp();
form.Show();
}
}
Updated code from Francesco Baruchelli's comment.
If I understand correctly what you are trying to do, you can keep a static List with the opened forms. Everytime an instance of your Form is opened you add it to the List, and everytime it is closed you remove it. The when you press the button you can check the size of the List. If it is 1 you create a new Form, open it and set the focus on it. If the size is already 2, you look in the List for the instance which is different from the one executing the click event. The code could be something like this:
private static List<Form1> openForms = new List<Form1>();
private void button1_Click(object sender, EventArgs e)
{
Form1 frm = null;
if (openForms.Count == 2)
{
foreach (Form1 aForm in openForms)
if (aForm != this)
{
frm = aForm;
break;
}
}
else
{
frm = new Form1();
frm.Show();
}
frm.Focus();
}
private void Form1_Load(object sender, EventArgs e)
{
openForms.Add(this);
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
openForms.Remove(this);
}