What is the previous window called in WPF - c#

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.

Related

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.

Data Retain After Changing DataContext/ Views in WPF

I am new to WPF and want to build an application which will do serial communication with the my driver and from program i can set values to the driver.
I have managed to make a UI as shown in this figure here . If i press Blue View as pointed by the arrow at last, the view of my window is like this. If i press the Red View Option then the display is like this
Setting button is where the arrow pointing at top right corner(below the close button of window) and when pressed my window will look like this.
Basically i am changing the BIG RECTANGLE content according to the button i have pressed for example (rectangle is blue when Blue view is clicked, rectangle filled up with Red and one label and a button to change the label when Red View is clicked)
So now my problem is I cannot retain the value i had set in this BIG RECTANGLE after i change the content of this BIG RECTANGLE. For example when i pressed the setting button and change the setting like this I am ready for communication in COM5 and the option to close the port can be pressed. Now before closing the port if I change the view of the BIG RECTANGLE by pressing Red View or Blue View then after press the setting button then i don't have that option to close port anymore and since I had already opened the com5 port earlier so when i try to open the port it will also give me error.
Please Help me with this. My visual studio solution explorer looks like this and My code in the button clicked event are as follows:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void SerialPortOnOFFButton_Clicked(object sender, RoutedEventArgs e)
{
MessageBox.Show("ON OFF Clicked");
}
private void SerialPortSettingButton_Clicked(object sender, RoutedEventArgs e)
{
DataContext = new SerialPortSettingView();
}
private void RedViewButton_Clicked(object sender, RoutedEventArgs e)
{
DataContext = new Redview();
}
private void BlueViewButton_Clicked(object sender, RoutedEventArgs e)
{
DataContext = new Blueview();
}
}
And my Solution explorer looks like this
If you want to just close your port you can implement IDisposable interface in your SerialPortSettingView class like this. Each time you change DataContext from SerialPortSettingView your port will be closed.
public class SerialPortSettingView : IDisposable
{
private FileStream _fileStream;
public SerialPortSettingView()
{
_fileStream = new FileStream("somefile.txt", FileMode.Open);
}
public void Dispose()
{
_fileStream?.Close();
}
}
Each time you change the view you are creating a new object to set the DataContext to, if you kept the individual objects as private fields you could then simply set the DataContext to these:
private SerialPortSettingView _serialPortSettingView;
private RedView _redView;
private BlueView _blueView;
public MainWindow()
{
_serialPortSettingView = new SerialPortSettingView();
_redView = new RedView();
_blueView = new BlueView();
InitializeComponent();
}
private void SerialPortOnOFFButton_Clicked(object sender, RoutedEventArgs e)
{
MessageBox.Show("ON OFF Clicked");
}
private void SerialPortSettingButton_Clicked(object sender, RoutedEventArgs e)
{
DataContext = _serialPortSettingView;
}
private void RedViewButton_Clicked(object sender, RoutedEventArgs e)
{
DataContext = _redview;
}
private void BlueViewButton_Clicked(object sender, RoutedEventArgs e)
{
DataContext = _blueview;
}
This way when you switch between views you'll be using the stored version and when you change values they will be stored in that View.
If I were doing this solution I would change the ContentControl to a TabControl (hide the headers) then create each View, with an accompanying ViewModel, as tabs. Then as each click event is fired you simply set the .SelectedIndex property of the TabControl. I'd create a MainWindowViewModel and set the MainWindow's DataContext to this in the constructor:
private MainWindowViewModel = new MainWindowViewModel();
public MainWindow()
{
DataContext = _mainWindowViewModel;
}
And put all the logic in the MainWindowViewModel (you need to use commands). Using code behind isn't what WPF was meant for, you can read up on it all here with a good tutorial to follow - MVVM Tutorial
I don't want to over complicate things and stuff you with too much information in one go but if you start off doing things this way it will be better, hope this helps.

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.

How to navigate between windows in WPF?

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

Why I can't call 'new Window().ShowDialog()' 2 times in Application startup?

Here's the XAML code:
<Application x:Class="WpfApplication2.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Startup="Application_Startup" />
Backing code:
using System.Windows;
namespace WpfApplication2
{
public partial class App : Application
{
private void Application_Startup(object sender, StartupEventArgs e)
{
new Window().ShowDialog();
new Window().ShowDialog();
}
}
}
Window shows only one time and then application exits. Why??
UPDATE: I know that windows should show up consequently. But after I close first window second does not show up at all
Try this
private void Application_Startup(object sender, StartupEventArgs e)
{
var w1 = new Window();
var w2 = new Window();
w1.ShowDialog();
w2.ShowDialog();
}
Paste form comment:
I think when you close first window,application checks whether there are other windows,and it doesn't find any (so application is closing), because second window haven't been created
Am I right to say that this will show the two windows consecutively and not simultaneously? When window1 is closed window2 will automatically open as the call is ShowDialog() which opens the window and then sets focus to it and doesn't open the other one until window1 is closed?
You can use a for loop to do so. Howerver, I have no idea why can't call directly.
for (int i = 0; i < 2; i++)
{
new Window().ShowDialog();
}
You are possibly ending the entire application in the Code used to close Window 1. If you are using something like Environment.Exit(0); this could be the issue.
ShowDialog wont allow you to create a same form unless its closed.
It's the difference between a modal and modeless form.
I think WPF is as the same reason...
and you can see ↓
Display Modal and Modeless Windows Forms
UPDATE:
Take a test by Stecya's answer , and it work fine...
protected override void OnStartup(StartupEventArgs e)
{
var w1 = new Window();
var w2 = new Window();
w1.ShowDialog();
w2.ShowDialog();
}

Categories