I have a MainWindow page and a LoadingWindow. The MainWindow has a button that closes itself and opens LoadingWindow. What I want is when the user closes the Loading window to go back to the MainWindow as a new instance.
MainWindow.xaml.cs
private void Button_Click(object sender, RoutedEventArgs e)
{
LoadingWindow load = new LoadingWindow(calibration , "MainWindow" , this);
Mouse.OverrideCursor = null;
Application.Current.MainWindow.Close();
load.ShowDialog(); // Exception is here the next time it is called
}
LoadingWindow.xaml.cs
private void Close_Button(object sender, RoutedEventArgs e)
{
MainWindow main = new MainWindow();
this.Close();
main.ShowDialog();
}
Now when I try to close the Loading window and press the Button_Click, the following error shows up at the load.ShowDialog() although I am declaring a new instance of it.
System.InvalidOperationException: Cannot set Visibility or call Show, ShowDialog, or WindowInteropHelper.EnsureHandle after a Window has closed
I read that you cannot open a window after you closed it, but I am having a new instance which should not make this problem.
On your main window don't use the Application.Current.MainWindow instance, use this.Close() instead.
private void Button_Click(object sender, RoutedEventArgs e)
{
LoadingWindow load = new LoadingWindow(...);
Mouse.OverrideCursor = null;
//Application.Current.MainWindow.Close();
this.Close();
load.ShowDialog(); // Exception is here the next time it is called
}
Refer to this thread & this for clarification on the difference.
Related
I know the current window can be used with "this" but is there anything I can use to call the previous window?
For example I have this code going off when I press a button
Buyer_Login BuyerWindow = new Buyer_Login();
Visibility= Visibility.Hidden;
BuyerWindow.Show();
I need to be able to go back to the first window and I need to close the BuyerWindow and I was going to do it with this.Close();
What can I do to make the first window's visibility visible again?
You could handle the Window.Closed event:
MainWindow.xaml.cs
private void OnClick(object sender, EventArgs e)
{
var loginWindow = new BuyerLogin();
loginWindow.Closed += OnBuyerLoginWindowClosed;
this.Visibility = Visibility.Hidden;
loginWindow.Show();
}
private void OnBuyerLoginWindowClosed(object sender, EventArgs e)
=> this.Visibility = Visibility.Visible;
You should consider to show the login window from the App.xaml.cs before you show your main window (recommended):
App.xaml.cs
private async void App_OnStartup(object sender, StartupEventArgs e)
{
var loginWindow = new BuyerLogin();
bool? dialogResult = loginWindow.ShowDialog();
if (dialogResult.GetValueOrDefault())
{
var mainWindow = new MainWindow();
mainWindow.Show();
}
}
App.xaml
<Application Startup="App_OnStartup">
<Application.Resources>
</Application.Resources>
</Application>
There is a collection of open windows.
App.Current.Windows;
It depends on exactly what you're doing opening windows.
If you start up then mainwindow will be [0] in that collection.
Say you then open an instance of window1.
That in turn opens an instance of window2.
There is a bit of a complication if you f5 in visual studio because it opens adorner windows.
Setting that aside for a moment.
When I write code to do what I describe above.
In Window2 I handle content rendered:
public partial class Window2 : Window
{
public Window2()
{
InitializeComponent();
}
private void Window_ContentRendered(object sender, EventArgs e)
{
var wins = App.Current.Windows;
wins[1].Close();
}
}
That instance of Window1 is closed.
Your new window is very likely the last window in that zero based collection and the previous one the window before that.
You could perhaps search the collection and find index for "this" and subtract one if you're doing more complicated things.
The chances are though, you want to close the window indexed by the count of that collection minus 2. Because it's zero based.
With my exploratory code, window1 closes with this:
private void Window_ContentRendered(object sender, EventArgs e)
{
var wins = App.Current.Windows;
wins[wins.Count - 2].Close();
}
Personally, I prefer single window apps and switch out the content in part of mainwindow. Leaving navigation buttons etc static in mainwindow.
If you're effectively opening one other window and closing the previous to do things then maybe you could consider a single window app instead.
I have a button that opens a WPF window which shows some calculation.
public void SomeButton_Click(object sender, RoutedEventArgs e)
{
Window1 win2 = new Window1();
win2.Show();
win2.Topmost = true;
}
I have a problem that if I change values in the program and press the button again, I have two open windows.
Is there a way that I can close win1 before opening the new version of win2?
I tried with win2.Close(), but since win2 is not known before the application creates it won't obviously work.
Thanks.
You could store a reference to the window in a variable in your class:
private Window2 win2;
public void SomeButton_Click(object sender, RoutedEventArgs e)
{
win2?.Close();
win2 = new Window2();
win2.Show();
win2.Topmost = true;
}
This will close any previous instance of Window2 that you have created and opened in the click event handler before you open a new window.
I have two Windows: MainWindow and AddAlarm.
AddAlarm is getting opened by a button which is in MainWindow. (MainWindow is still active)
When I typed in my data in AddAlarm, I press the "OK" button and AddAlarm get's closed. After pressing "OK" I want to activate a function which is in MainWindow.cs
But how do I do that?
Opens new window (AddAlarm)
private void Button_AddAlarm_Click(object sender, RoutedEventArgs e)
{
AddAlarm frm = new AddAlarm();
frm.Show();
frm.Activate();
}
Pressing "OK"-button in AddAlarm window
private void Button_OK_Click(object sender, RoutedEventArgs e)
{
// some code which activates function in MainWindow
}
Function in MainWindow
public void Refresh()
{
string[] refresh = new string[0];
refresh = File.ReadAllLines("Alarms.txt");
}
There might be a clever and easy solution, but I just don't know how to do that.
I appreciate your help,
thanks
This totally depends on you but here is a simple solution.
private void Button_AddAlarm_Click(object sender, RoutedEventArgs e)
{
AddAlarm frm = new AddAlarm(this); // pass a reference to main window
frm.Show();
frm.Activate();
}
you'll need to create a private MainWindow mainWindow; in AddAlarm window and assign it in the constructor.
Then
private void Button_OK_Click(object sender, RoutedEventArgs e)
{
this.mainWindow.Refresh();
}
More complicated, but more "idiomatic", would be to rely on callback events (like an AlarmAdded event with an Alarm parameter which would be registered right after the AddAlarm is created and raised by the AddAlarm window when it's done).
The approach I would probably take would be to just open AddAlarm modally--that way you can read the information you need from the AddAlarm window in the same block.
private void Button_AddAlarm_Click(object sender, RoutedEventArgs e)
{
AddAlarm frm = new AddAlarm();
// ShowDialog waits until AddAlarm is closed before returning
frm.ShowDialog();
// Recommended to add a check on frm.DialogResult to verify whether the user OK'd or Cancelled.
if (frm.DialogResult = DialogResult.Ok) {
AlarmSettings settings = frm.AlarmSettings;
Alarm createdAlarm = new Alarm (AlarmSettings);
}
}
I'm trying to bring my MainWindow into view when I close a specific window within the same application. I have tried to do this but with the code I have created it just creates a new instance of MainWindow and I end up having 2 MainWindows instead of a desired one. Here is the code below that I have got.
private void Weight_Click(object sender, RoutedEventArgs e)
{
try
{
MultipleConverters.Windows.Weight WeightCalculation = new Windows.Weight();
WeightCalculation.Show();
this.WindowState = WindowState.Minimized;
}
// This code above works fine and minimizes the mainwindow and brings into view the selected window.
private void Quit_Click(object sender, RoutedEventArgs e)
{
this.Close();
MainWindow bringIntoView = new MainWindow();
bringIntoView.Show();
}
// Now with this code above is the problem code. This code is within the new window and what Iam trying to achieve is when this window is closed the mainwindow will be brought back into scope rather than creating a new instance of it, and leaving me with 2 Mainwindows rather than the desired 1 Mainwindow. any help would be great.
Use the Owner property to store the reference to the main window, you can then use that property to bring the window back up.
private void Weight_Click(object sender, RoutedEventArgs e)
{
try
{
MultipleConverters.Windows.Weight WeightCalculation = new Windows.Weight();
WeightCalculation.Owner = this;
WeightCalculation.Show();
this.WindowState = WindowState.Minimized;
}
elsewhere
private void Quit_Click(object sender, RoutedEventArgs e)
{
this.Close();
Owner.WindowState = WindowState.Normal;
}
However based on the behavior you are showing you may want to look in to using ShowDialog() instead of minimizing the parent window and use that instead.
private void Weight_Click(object sender, RoutedEventArgs e)
{
try
{
MultipleConverters.Windows.Weight WeightCalculation = new Windows.Weight();
WeightCalculation.Owner = this;
WeightCalculation.ShowDialog(); //The code pauses here till the dialog is closed.
}
Application.Current.MainWindow.Activate();
There is a handy property Application.Current.MainWindow that you can use to access the main window declared in App.xaml, you should just be able to show it by calling:
Application.Current.MainWindow.Show();
Application.Current.MainWindow.Activate();
To simplify things, you could create a static method on your MainWindow which handles all this:
public static void TryReveal()
{
var mainWindow = Application.Current.MainWindow;
if (mainWindow == null)
{
// The main window has probably been closed.
// This will stop .Show() and .Activate()
// from throwing an exception if the window is closed.
return;
}
if (mainWindow.WindowState == WindowState.Minimized)
{
mainWindow.WindowState = WindowState.Normal;
}
// Reveals if hidden
mainWindow.Show();
// Brings to foreground
mainWindow.Activate();
}
And then your other windows can just call MainWindow.TryReveal(). That way your windows don't need any reference to the main window as the static method handles it.
The best way you could handle this in WPF though is (I think) using a messaging implementation (eg. MVVM Light's Messaging system, or Caliburn.Micro's EventAggregator). Your MainWindow would subscribe to a "MainWindowViewStateMessage" or something like that (defined by you) and your other windows would pass it through the messaging system. The main window would intercept it and do the necessary work.
private void Quit_Click(object sender, RoutedEventArgs e)
{
this.Close();
MainWindow bringIntoView = new MainWindow();
bringIntoView.Show();
}
You're creating a new instance of MainWindow and then showing it. This is why a new MainForm is shown.
One thing you can do is set a property on the WeightCalculation window like this:
public MainWindow _mainWindow { get; set; }
Before showing the WeightCaculation, set _mainWindow to your current instance of MainWindow :
MultipleConverters.Windows.Weight WeightCalculation = new Windows.Weight();
WeightCalculation._mainWindow = this;
WeightCalculation.Show();
this.WindowState = WindowState.Minimized;
and from the new form you can now interact with the MainWindow.
I have tried to set up a click event for a button that opens another window,but the error I'm getting at NavigationService is that the project doesn't contain a definition for it.
This is how I'm trying to call the page at present:
private void conditioningBtn_Click(object sender, RoutedEventArgs e)
{
this.NavigationService.Navigate(new Uri("TrainingFrm.xaml", UriKind.RelativeOrAbsolute));
}
Can someone point me in the right direction with this or show alternatives to this method for window navigation?
NavigationService is for browser navigation within WPF. What you are trying to do is change to a different window TrainingFrm.
To go to a different window, you should do this:
private void conditioningBtn_Click(object sender, RoutedEventArgs e)
{
var newForm = new TrainingFrm(); //create your new form.
newForm.Show(); //show the new form.
this.Close(); //only if you want to close the current form.
}
If, on the other hand, you want your WPF application to behave like a browser, then you would need to create Pages instead of Forms, and then use a Frame in your application to do the navigation. See this example.
If you want to navigate from Window to Window:
private void conditioningBtn_Click(object sender, RoutedEventArgs e)
{
Window1 window1 = new Window1();
// window1.Show(); // Win10 tablet in tablet mode, use this, when sub Window is closed, the main window will be covered by the Start menu.
window.ShowDialog();
}
If you want to navigate from Window to Page:
private void conditioningBtn_Click(object sender, RoutedEventArgs e)
{
NavigationWindow window = new NavigationWindow();
window.Source = new Uri("Page1.xaml", UriKind.Relative);
window.Show();
}
In order to use NavigationService you should use the Page and not the Window class