XAML C# - Opening Windows - c#

I am starting XAML coding and cannot for the life of it find out if a window is openen or not (once openen by clicking a button)
For now, it keeps opening unlimited amounts of windows. What I want is that once a window is openen, it won't open again, even if you press the button again.
here's my code, but with this it's not showing a window at all!
What am i doing wrong?
private void System_Agents(object sender, RoutedEventArgs e)
{
var newW = new SystemAgents();
if ( newW == null )
{
newW.Show();
}
else newW.Activate();

When you create the window the first time, store the newly-created window instance in a member variable of the class that creates it. Then check that member variable before creating it the next time you want that window, and if it's not null, don't create another.

I solved it! After long searching, it was actually quite easy!
Here's the code:
SystemAgents window; //Presets a variable to SystemAgents window
private void System_Agents(object sender, RoutedEventArgs e) //Call method
{
if ( window == null )
{
window = new SystemAgents(); //Sets variable "window" to the window "SystemAgents"
window.Show(); //Shows the window "System Agents"
window.Owner = this; //Determins the owner of the window is the main Application
window.Closed += new EventHandler(AddItemView_Closed); //Sets a new method (defined below) to what happens if you close the window so window will close when app closes.
}
else window.Activate(); //Will set the window as active.
//newW.ShowDialog(); //Will Show Window, but unable to do anything else other then the window
}
void AddItemView_Closed(object sender, EventArgs e)
{
window = null;
}

Related

What is the previous window called in WPF

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.

WPF - Go back to first window from second window

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.

How do I show a new window after having closed the MainWindow?

I'm trying to do what is described in this post, display a log in window and when user successfully logs in, close it and open the main window of the application.
If the user logs on successfully, then I want to show the main window, if not, I want to exit the application
but the provided answers (at the time of posting this question) do not work for me since my code to show the windows is running from the App.cs.
I know the reason, its because the first window that starts up is automatically set to be the MainWindow of the application and when I call Close() on it, it exits the application. So the second window doesn't have a chance to open.
My question is how to overcome this? Or is this just not possible the way I described?
public partial class App : Application
{
public App(){}
private void Application_Startup(object sender, StartupEventArgs e)
{
LoginScreen f = new LoginScreen(); //becomes automatically set to application MainWindow
var result = f.ShowDialog(); //View contains a call to Close()
if (result == true) //at this point the LoginScreen is closed
{
MainWindow main = new MainWindow();
App.Current.MainWindow = main;
main.Show(); //no chance to show this, application exits
}
}
}
You can change application shutdown mode to OnExplicitShutdown and then call Application.Shutdown(0) whenever you want to. For example:
public App()
{
App.Current.ShutdownMode = ShutdownMode.OnExplicitShutdown;
}
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
if (MessageBox.Show("Continue?", "", MessageBoxButton.YesNo) == MessageBoxResult.No)
App.Current.Shutdown(0);
}
Here in the constructor I'm changing application shudown mode and calling Shutdown method if I need to.
Caution: When you change ShutdownMode make sure to call Shutdown method otherwise your application will be in memory even after main window closes. I've overrided OnClosed method in my MainWindow to do that:
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
App.Current.Shutdown(0);
}
App.xaml : (In this file set the start window with the login view)
StartupUri="LoginWindow.xaml"
LoginWindow.xaml : (A file with a login window view)
LoginWindow.xaml.cs : (Code Behind for the view. Place here the function assigned to login. )
private void Login_Click(object sender, RoutedEventArgs e)
{
//Access control. If correct, go ahead. Here you must create a condition check
MainWindow main = new MainWindow();
main.Show();
this.Close();
}

How to bring MainWindow into view when closing a window?

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.

Prevent to close parent window if child windows are active

I am developing multiple instance WPF application. Application has a grid in a main screen and on double click of grid row, it opens child window. It has also functionality to open multiple child windows on double click of grid row from main screen.
Can anybody help me to prevent parent window to be close if child windows are active? So user can not able to close main window if child windows are active.
Set Owner property for those childs to Main Windows:
private void Button_Click(object sender, RoutedEventArgs e)
{
var wnd = new Window();
wnd.Owner = this;
wnd.Show();
}
Then in Main Window closing event handler:
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
if (this.OwnedWindows.Count > 0)
{
MessageBox.Show("Child windows exists, you have to close'em first");
e.Cancel = true;
}
}
As a final point it could be helpful for you to know that you can get from anywhere in your code the app main windows with this:
System.Windows.Application.Current.MainWindow
So if you are using MVVM the above will help you in setting the Owner property.
You have two options:
1- You can use ShowDialog() to open the child window, but user can't interact with the parent window till the child is closed.
2- You can check all windows that are currently opened by checking
Application.Current.Windows
and then you can determine whether you want to close your window or not
Edit:
add the following event handler to your Parent.Closing event
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
foreach (var item in Application.Current.Windows)
{
Window window = item as Window;
if (window.Title == "YourChildWindowTitle")
{
// show some message for user to close childWindows
e.Cancel = true;
break;
}
}
}
In window closing command pass that if the child window is open disable closing functionality.
Or
you what you can do is make canexecute = false when a pop up is open and closing command is triggered.
Attach a function to the main window's 'Closing' event, and check to see if the child window is open. if it is, set
e.cancel = true;

Categories