I'm new to WPF and couldn't find an answer to to this issue:
I have 3 windows I want to navigate between-
MainWindow -> Window1 -> Window2
On cancel button click on Window2 I want to return to Window1.
I found this code to navigate between 2 windows, but not between 3 as I need:
MainWindow:
private void Window1_Click(object sender, RoutedEventArgs e)
{
Window1 window1 = new Window1();
window1.Show();
this.Hide();
}
Window1:
private void btn_Cancel_Click(object sender, RoutedEventArgs e)
{
Application.Current.MainWindow.Show();
this.Close();
}
private void btn_Window2_Click(object sender, RoutedEventArgs e)
{
Window2 window2 = new Window2();
window2 .Show();
this.Hide();
}
Window2:
private void btn_Cancel_Click(object sender, RoutedEventArgs e)
{
this.Close();
//what should I write to show Window1 again?
}
Here is an example of a navigation service class that holds a stack of navigated windows.
public static class NavigationService
{
static NavigationService()
{
NavigationStack.Push(Application.Current.MainWindow);
}
private static readonly Stack<Window> NavigationStack = new Stack<Window>();
public static void NavigateTo(Window win)
{
if(NavigationStack.Count > 0)
NavigationStack.Peek().Hide();
NavigationStack.Push(win);
win.Show();
}
public static bool NavigateBack()
{
if (NavigationStack.Count <= 1)
return false;
NavigationStack.Pop().Hide();
NavigationStack.Peek().Show();
return true;
}
public static bool CanNavigateBack()
{
return NavigationStack.Count > 1;
}
}
You can use it from your views' code behind :
public void OnNextClicked(object sender, EventArgs args)
{
NavigationService.NavigateTo(new Window2());
}
public void OnPreviousClicked(object sender, EventArgs args)
{
NavigationService.NavigateBack();
}
The static constructor adds the main view started from your App.xaml StartupUri to the navigation stack as the initial view.
If your application has a growing complexity you may also have a look at tools such as prism navigation system.
Change the way you show your windows like this:
private void Window1_Click(object sender, RoutedEventArgs e)
{
Hide();
new Window1().ShowDialog();
ShowDialog();
}
And use the DialogResult property to hide your windows (except the main window):
private void btn_Cancel_Click(object sender, RoutedEventArgs e)
{
DialogResult = false;
}
Related
So I have a Page(Homepage.xaml), when I click a button on this page it opens a prompt(Prompt.xaml).
This prompt is just a Window that I've made and executed using a window.ShowDialog(); method in the Homepage.cs. I've been able to add a little code and when the NO button is clicked the prompt window is closed, now where I'm finding trouble is the YES button.
What I want is for the YES button to take me back to MainWindow, which I've been able to achieve so far, but when it opens the previous Homepage.xaml
is still there and I don't know how to close the Page from the prompt window, if that's even possible?
Another thing is, when the MainWindow opens it kinda pops up, can I make it so that it just lands on the page instead of opening/popping up like a new program?
Heres the Code.
Homepage.cs
public partial class User_Homepage : Page
{
public static Page pager { get; set; }
public User_Homepage()
{
InitializeComponent();
}
public void UserLogoutBtn_Click(object sender, RoutedEventArgs e)
{
var lovmsgb = new Custom_MessageBoxes.LogoutVerification();
lovmsgb.ShowDialog();
}
}
Prompt.cs
public partial class LogoutVerification : Window
{
public LogoutVerification()
{
InitializeComponent();
}
private void YesLogoutBtn_Click(object sender, RoutedEventArgs e)
{
this.Close();
MainWindow window = new MainWindow() { WindowStartupLocation = WindowStartupLocation.CenterScreen};
window.Show();
}
private void NoLogoutBtn_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}
And MainWindow.cs just in case
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void BtnClickP1(object sender, RoutedEventArgs e)
{
mainFrame.Content = new Page1();
}
private void AdminBtn_Click(object sender, RoutedEventArgs e)
{
mainFrame.Content = new Page3();
}
}
To check what button was clicked you should assign DialogResult in your DialogWindow:
private void YesLogoutBtn_Click(object sender, RoutedEventArgs e)
{
DialogResult = true;
this.Close();
}
private void NoLogoutBtn_Click(object sender, RoutedEventArgs e)
{
DialogResult = false;
this.Close();
}
Now make method to call dialog in your MainWindow and pass it as argument to Page1:
private void AskDialog()
{
Dialog dialog = new Dialog();
if (dialog.ShowDialog() == true)
{
mainFrame.Content = null;
}
else
{
// False action
}
}
private void button1_Click(object sender, RoutedEventArgs e)
{
frame.Content = new Page1(AskDialog);
}
In Page1 just call this action after button is pressed:
public User_Homepage(Action askDialog)
{
InitializeComponent();
AskDialog = askDialog;
}
private readonly Action AskDialog;
private void UserLogoutBtn_Click(object sender, RoutedEventArgs e)
{
AskDialog();
}
I have 3 windows and I am able to switch between them fine. The problem i am running into is the windows aren't saving the data when hidden. I think somewhere they are getting disposed, but i'm not sure how. I have a textbox on two windows to test this. It worked fine when there was only two windows, but adding the third created this problem. Here is my main window.
public partial class MainWindow : Window
{
private AutoImport auto;
private DTLegacy dleg;
public MainWindow()
{
InitializeComponent();
}
public MainWindow(AutoImport parent)
{
InitializeComponent();
auto = parent;
}
public MainWindow(DTLegacy parent)
{
InitializeComponent();
dleg = parent;
}
private void btnAutoImport_Click(object sender, RoutedEventArgs e)
{
this.Hide();
if (auto == null) { auto = new AutoImport(); }
auto.Show();
}
private void btnDTLegacy_Click(object sender, RoutedEventArgs e)
{
this.Hide();
if (dleg == null) { dleg = new DTLegacy(); }
dleg.Show();
}
}
Window 1
public AutoImport()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
this.Hide();
MainWindow main = new MainWindow(this);
main.Show();
}
Window 2
public DTLegacy()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
this.Hide();
MainWindow main = new MainWindow(this);
main.Show();
}
I'm thinking the answer might be to create a window class of some sort, but i'm not sure what this would look like.
Why are you creating a new MainWindow instance each time? You're currently hiding it, so show it again instead of creating a new one.
Assuming it's the main Window of your application and AutoImport/DTLegacy are "child" windows, one solution would be to pass the MainWindow instance as parameter of the "child" windows, so you can call .Show() easily:
private MainWindow parent;
public AutoImport(MainWindow parent)
{
InitializeComponent();
this.parent = parent;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
this.Hide();
this.parent.Show();
}
Description - I have main window having status label which shows status in the form of connected and disconnected. When i create a object(parent window) in child window and set label status it wont be reflected in parent window. .I also tried, took a one Boolean variable and set to value 1 in child window code,but when i access that variable in parent window ,i got by default value that is zero.
/// My parent window code
public partial class MainWindow : Window
{
public CompSetting obj = new CompSetting();
public MainWindow()
{
InitializeComponent();
}
private void click(object sender, MouseButtonEventArgs e)
{
CompSetting compPortseting = new CompSetting();
compPortseting.ShowDialog();
}
private void button_Click(object sender, RoutedEventArgs e)
{
if (obj.flag == 1) // Here i get by defult value 0 . but already set to 1 on child window. In short cant access flag variable value.
{
LblPortStatus_lable.Content = "chetas";
}
else
{
LblPortStatus_lable.Content = "rahul";
}
}
}
// My child window code
public partial class CompSetting : Window
{
public int flag ;
public CompSetting()
{
InitializeComponent();
}
private void button_Click(object sender, RoutedEventArgs e)
{
flag = 1;
}
}
private void click(object sender, MouseButtonEventArgs e)
{
if(obj != null)
{
obj.ShowDialog();
}
}
Do not create a new object, just use the existing one.
Extra
Instead of creating an instance of the child window consider creating an instance of a settings object. The child window would then get a reference to the settings object and modify it:
public partial class MainWindow : Window
{
public CompSetting settings = new CompSetting();
public MainWindow()
{
InitializeComponent();
}
private void click(object sender, MouseButtonEventArgs e)
{
var settingsDialog = new SettingDialog(settings);
settingsDialog.ShowDialog();
}
private void button_Click(object sender, RoutedEventArgs e)
{
if (settings.Flag == 1)
{
LblPortStatus_lable.Content = "chetas";
}
else
{
LblPortStatus_lable.Content = "rahul";
}
}
}
// My child window code
public partial class SettingDialog : Window
{
private CompSettings settings
public SettingsDialog(CompSettings settings)
{
this.settings = settings;
}
private void button_Click(object sender, RoutedEventArgs e)
{
this.settings.Flag = 1;
}
}
public class CompSettings
{
public int Flag;
}
I am have trouble using multiple windows in WPF and switching between them using a button. In theory my application should have 2 buttons, one forward and one back each on respectively changing the window to the previous and next window.
Unfortunately I get a Stackoverflow error, through my research I feel that it has something to do with me creating new windows that are creating the window again when the previous window is created, thus making a horrible loop. However I don't know where I can put the window creation code to stop this problem or if there are other ways to fix this.
Here is code for my windows:
First Window
public partial class Presenation_1 : Window
{
Presentation_2 p2 = new Presentation_2();
MainWindow M = new MainWindow();
public Presenation_1()
{
InitializeComponent();
}
private void btnForward_Click(object sender, RoutedEventArgs e)
{
this.Close();
p2.Show();
}
private void btnBack_Click(object sender, RoutedEventArgs e)
{
this.Close();
M.Show();
}
}
Second Window
public partial class Presentation_2 : Window
{
Presentation_3 p3 = new Presentation_3();
Presenation_1 p1 = new Presenation_1();
public Presentation_2()
{
InitializeComponent();
}
private void btnForward_Click(object sender, RoutedEventArgs e)
{
this.Close();
p3.Show();
}
private void btnBack_Click(object sender, RoutedEventArgs e)
{
this.Close();
p1.Show();
}
}
Third Window
public partial class Presentation_3 : Window
{
Presentation_4 p4 = new Presentation_4();
Presentation_2 p2 = new Presentation_2();
public Presentation_3()
{
InitializeComponent();
}
private void btnForward_Click(object sender, RoutedEventArgs e)
{
this.Close();
p4.Show();
}
private void btnBack_Click(object sender, RoutedEventArgs e)
{
this.Close();
p2.Show();
}
}
Fourth Window
public partial class Presentation_4 : Window
{
Presentation_3 p3 = new Presentation_3();
MainWindow M = new MainWindow();
public Presentation_4()
{
InitializeComponent();
}
private void btnForward_Click(object sender, RoutedEventArgs e)
{
this.Close();
M.Show();
}
private void btnBack_Click(object sender, RoutedEventArgs e)
{
this.Close();
p3.Show();
}
}
Thanks in advance
Don't create your Windows before the button is clicked, you can create them in the event handler:
private void btnForward_Click(object sender, RoutedEventArgs e)
{
var p2 = new Presentation_2();
this.Close();
p2.Show();
}
When you create a windows, you create 2 other windows with
new Presentation_X()
This new windows is automaticaly show and itself open 2 other windows.
You can create this windows once in the Mainwindow (auto hide this one), pass the reference in constructor and not close these windows. Quick example (not tested) :
public partial class Presenation_X : Window
{
private Window preview;
private Window next;
public Presenation_X(Window w1, Window w2)
{
this.preview = w1;
this.next = w2;
InitializeComponent();
}
private void btnForward_Click(object sender, RoutedEventArgs e)
{
this.next.Show();
this.Hide();
}
private void btnBack_Click(object sender, RoutedEventArgs e)
{
this.preview.Show();
this.Hide();
}
}
WPF - From Window1 I'm trying to maximize a previously minimized Window2.
This is how I am opening Window2 (I hope to use the same button to maximize it)
public partial class Window1 : Window
{
private bool SecondWindowOpen = false;
public Window1()
{
InitializeComponent();
}
private void OpenSecondWindow_Click(object sender, RoutedEventArgs e)
{
if (SecondWindowOpen == false)
{
new Window2().Visibility = Visibility.Visible;
this.SecondWindowOpen = true;
}
else
{
}
}
}
Window2 has 2 buttons, one minimizes Window2 while the other closes it.
public partial class Window2 : Window
{
public Window2()
{
InitializeComponent();
}
private void btnMinimize_Click(object sender, RoutedEventArgs e)
{
this.WindowState = WindowState.Minimized;
}
private void btnClose_Click(object sender, RoutedEventArgs e)
{
Close();
}
}
So after opening Window2, I click btnMinimize. Now I'm back in Window1 and would like to click OpenSecondWindow and return Window2 to its original position. I would think this is a syntax issue, but I have been unable to find any examples.
Thank You
public partial class Window1 : Window
{
private bool SecondWindowOpen = false;
private Window2 window2;
public Window1()
{
InitializeComponent();
}
private void OpenSecondWindow_Click(object sender, RoutedEventArgs e)
{
if (SecondWindowOpen == false)
{
window2 = new Window2();
window2.Visibility = Visibility.Visible;
this.SecondWindowOpen = true;
}
else
{
//do whatever you want with window2, like window2.Close();
//or window2.Visibility = Visibility.Hidden;
}
}
}