Navigation between Pages and Windows in WPF - c#

I have an issue that I am trying to resolve. I have two WPF windows. Those windows house the pages with content. My problem is not navigating page to page but rather window to window. here is an example of the code:
LoginPortal Design
<Grid>
<Frame x:Name="MainFrame" NavigationUIVisibility="Hidden"/>
</Grid>
LoginPortal Code
public LoginPortalMain()
{
InitializeComponent();
MainFrame.Navigate(new Uri("/Pages/LoginPortal.xaml", UriKind.RelativeOrAbsolute));
}
This is my Login portal that houses 4 buttons. Each button opens the second window which is houses several pages.
private void BtnSales_Click(object sender, RoutedEventArgs e)
{
var w = Application.Current.Windows[0];
w.Hide();
MainWindow mn = new MainWindow();
mn.Content = new SalesPage();
mn.Show();
}
When this button is clicked it opens the second WPF Window which is where several pages are housed. There is no problem with navigation. The problem starts when I wire the Closing event from the MainWindow to go back to the LoginPortalMain
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
LoginPortalMain lgm = Application.Current.MainWindow as LoginPortalMain;
lgm.Show();
}
It then goes back to the start again. Now my problem is if I click on the same button again. It just duplicates everything. Then on closing anything it just adds new windows. If I then exit out of any window, it throws an error in picture below. My question is, is there a way to either dispose of the navigation once the MainWindow is closed. So there is no duplicate windows once you close the mainWindow a second time. I have used navigation before on a single window but not on multiple windows.
I may have to rethink this whole structure and use custom UserControls and figure out the animation sequence from Pages to UserControls. However, any help would be greatly appreciated.
enter image description here
enter image description here
enter image description here
enter image description here
enter image description here

If you only want to be able to open one instance of the new window try showing and hiding a single window instance.
When the open window button is pressed create the window if need and show it.
private OtherWindow mOtherWindow;
private void OpenWindowButtonClick(object sender, RoutedEventArgs e)
{
mOtherWindow ??= new OtherWindow(); //initialize child window on first call
mOtherWindow.Show();
}
When the other window is closed hide it and cancel the close request. You could also reset the other window state here for the next time it is shown.
private void OtherWindowClosingEvent(object sender, System.ComponentModel.CancelEventArgs e)
{
((Window)sender).Hide();
Application.Current.MainWindow.Activate();
e.Cancel = true;
}

Related

Trouble going from one form to another using buttons

this is my frmMain image
I have been struggling with this all day. I have 7 buttons in my nav menu. I have my main form which all those buttons are placed and 7 forms that I will connect to my 7 buttons. 1 form for each button. When I go to another form the previous form I opened is still there. I tried using hide and close to exit the other forms but it was not working for me. I'm also using none border form
btnItems to frmItems
btnUsers to frmUsers
btnSuppliers to frmSuppliers
btnStocks to frmStocks (and so on with the 3 more buttons connected to different forms)
This is the code.
private void btnItems_Click(object sender, EventArgs e)
{frmItems op = new frmItems();
op.Show();
}
private void btnSuppliers_Click(object sender, EventArgs e)
{
frmSuppliers op = new frmSuppliers();
op.Show();
}
Although I don't understand EXACTLY what you are trying to accomplish, is showing the forms as a modal dialog an option? This would ensure that a window must be closed before allowing control to go back to the main form and allow another window to be opened.
private void btnSuppliers_Click(object sender, EventArgs e)
{
using (var op = new frmSuppliers())
op.ShowDialog(this);
}

Taskbar icon disappears when minimizing form application c#

When I'm changing windows(forms), my application's icon disappears from taskbar. So for opening the application, users need to click ALT+TAB to select the form which is hidden from taskbar. After users choose application, icon comes to taskbar again. I don't want my applcation icon disappears from taskbar.
My codes are below:
//Program.cs
[STAThread]
static void Main()
{
Application.Run(new LoginPage());
}
Login Page is application's first screen that gets username and password. After clicking submit button application is going to main page.
//LoginPage.cs
private void submitBtn_Click(object sender, EventArgs e)
{
MainPage mainPage= new MainPage();
mainPage.Show();
this.Hide();
}
Lets say I have a button on main page for going to another form. Here when I click the page1 button taskbar icon disappears.
//MainPage.cs
private void page1Btn_Click(object sender, EventArgs e)
{
Page1 page1 = new Page1();
page1.Show();
this.Hide();
}
After some research I found one solution for that but there is another problem which I cannot minimize the form correctly.
When I change the codes above with below
//MainPage.cs
private void page1Btn_Click(object sender, EventArgs e)
{
Page1 page1= new Page1();
page1.ShowInTaskbar = false;
page1.Owner = this;
page1.ShowDialog();
this.Hide();
}
Here, I also need to modify Page1 as below
//Page1.cs
private void Page1_FormClosed(object sender, FormClosedEventArgs e)
{
MainPage mainPage = new MainPage();
mainPage.Show();
}
Here I can successfully go to page1 step by step (without disappearing the taskbar icon). When I minimize the page1, it minimizes the application as expected but when I maximize the application from taskbar, I expect Page1 should maximizes but MainPage maximizes with an minimized Page one like below image.
I only want to correct these problems. I hope there is experts which experienced these things there.
Problem is solved.
The problem was, I was maximizing the form from properties of the page.
Instead of maximizing it from properties, I do it manually from Page Load and its solved.
this.Bounds = Screen.PrimaryScreen.WorkingArea;
In MetroFramework, I have the same problem. When my application starts (in the FORM_LOAD) , I programmatically maximize and the icon disappears. Checking the MetroFramework code, the problem is caused by ShadowType. If you change the ShadowType to None:
this.ShadowType= MetroFormShadowType.None;
the issue is resolved. I hope the solution works

How do I return to a window after opening a second?

My application is of such a nature that I need to jump around many windows consecutively. From my menu window I need to open another window (from the selection) and the disable or close the menu window.
What I'm currently using is window.show and then this.close() method to close the menu window.
Ex:
private void MainMenuControl_Link1MouseDown(object sender, RoutedEventArgs e)
{
// Utilities
UtilitiesMenyWindow UtilitiesMenyWindow = new UtilitiesMenyWindow(); // Assign Variable to window
UtilitiesMenyWindow.Show(); // Open window
this.Close(); // close current window
}
Then from within the new windows I just reopen the MainMenu window using the same method.
private void Utilities_Link3MouseDown(object sender, RoutedEventArgs e)
{
// Return to Main
MainMenuWindow MainMenu = new MainMenuWindow(); // Assign Variable to window
MainMenu.Show(); // Open Main window
this.Close(); // close login window
}
I then also keep a public variable class with static variables to store all the variables that are generic to all the windows.
All this is working fine for me except for one snag. If I were to call the UtilitiesMenyWindow from another window (not MainWindow) it's going to return to the MainMenu instead of the window I opened it from.
Is there a easier more generic way to return to the window that opened the secondary window without having to tell it to close itself and open a specific window (in this case it's "hardcoded" to MainMenu) (Obviously I first open and then close)
I was looking at the Unloaded event but how do I get the original window to stay hidden until this event occurs without it having to sit there and wait in a loop which is not a good idea.
Maybe somebody can guide me in a way to set it up as an automatic event that "fires" the event-handler, which in turn then activates the previous window?
Rather than closing windows, you could consider hiding them. That way, you could pass a reference to the calling window whenever you create a new window.
i.e.
UtilitiesMenyWindow UtilitiesMenyWindow = new UtilitiesMenyWindow();
UtilitiesMenyWindow.CallingWindow = this;
UtilitiesMenyWindow.Show();
this.Hide();
then, when you want to close the new window and return:
this.Hide();
this.CallingWindow.Show();
You could just close the original window - since all your windows are probably inheriting from Window class you just need to store the current window in a 'Window' typed variable on the utilities menu
This way you can continue doing what you are doing:
e.g.
private void MainMenuControl_Link1MouseDown(object sender, RoutedEventArgs e)
{
// Utilities
UtilitiesMenyWindow UtilitiesMenyWindow = new UtilitiesMenyWindow(); // Assign Variable to window
UtilitiesMenyWindow.ReturnWindow = this;
UtilitiesMenyWindow.Show(); // Open window
this.Hide(); // hide current window
}
And add
Window _returnWindow;
on your utility window class
Then in that class on the close method you can call the original window type:
private void Utilities_Link3MouseDown(object sender, RoutedEventArgs e)
{
// Return to original
_returnWindow.Show();
this.Close(); // close login window
}
This is of course assuming you don't kill the original window

Closing a secondary window completely

It appears that second windows are not closing. Here is what I am doing....
I have created a new WPF project.
I placed a button in the main window.
I put the following code in the button to launch a second window and hide the main.
private void button1_Click(object sender, RoutedEventArgs e)
{
var projectWindow = new NewProjectInfo();
this.Hide();
projectWindow.Show();
}
-The new window is a blank window with nothing on it.
-In the "close" event of the new window I put the code to show the main window again.
private void Window_Closed(object sender, EventArgs e)
{
var mainWindow = new MainWindow();
mainWindow.Show();
}
If I run the program and close the main window without opening the second window, the programs ends like I would like it to.
If I click the button on the main window, taking me to the second window, then close that window, taking me back to the main window, then close the main window the program does not end. (meaning I have to hit the stop button in visual studio to get it to end)
It's like visiting the second window leaves some kind of process running.
So, when I close the main window I can just run the:
Application.Current.Close();
But is that safe? Do I run the chance of leaving something hanging? Or is there a better way to close that second window so when I close the main the program will end?
These lines
var mainWindow = new MainWindow();
mainWindow.Show();
create a new MainWindow and show it. The original MainWindow is still hidden.
To resolve your problem, you need a reference to the original MainWindow instance.
Perhaps you could pass this reference when you build your secondary window
// Create a NewProjectInfo instance and pass this
var projectWindow = new NewProjectInfo(this);
this.Hide();
projectWindow.Show();
And in the constructor of the projectWindow, save the reference passed in a global var
var MainWindow _originalReference;
public NewProjectInfo(MainWindow original)
{
_originalReference = original;
}
now the window close event could use the referenced window
private void Window_Closed(object sender, EventArgs e)
{
_originalReference.Show();
}
Instead of creating a new Main window, can you simply call Application.Current.MainWindow.Show(); in your closed event handler?

ClickOnce and inactive main window

My application uses ClickOnce technology for deployment. However I have problem when user starts using the application. The scenario for reproducing the problem is as follows:
User clicks on application's shortcut in order to run the application
ClickOnce's "Launching application" dialog box appears in order to check for updates
"Launching application" dialog box disappears
Splashscreen appears
Main window (login window) appears - however it's not active nor has a focus
Because main window is not active, user has to click on it before he/she can start typing username and password. How can I resolve this problem so the main window is active after it appears? I've tried the following code but it's not working:
protected override void OnInitialized(EventArgs e)
{
while (!this.IsFocused) { this.Focus(); WPFWaitForPriority.WaitForPriority(DispatcherPriority.Background); }
base.OnInitialized(e);
}
Most likely you're giving focus to the splash screen. So when it closes nothing has focus any longer. After closing the form call the Select Method on the control you want to have focus(the username textbox i'm guessing).
Select for Focus
try this code:
Pseudo code:
OnShown
this.focus
I mean.
Use diffrent event.
I have a WPF / ClickOnce application and don't have the same problem. I don't use the StartupUri of App.xaml, I manually show the login window instead as follows in App.xaml.cs:
protected override void OnStartup(StartupEventArgs e)
{
this.DispatcherUnhandledException += new System.Windows.Threading.DispatcherUnhandledExceptionEventHandler(App_DispatcherUnhandledException);
this.Exit += new ExitEventHandler(App_Exit);
base.OnStartup(e);
ShowLogin();
}
private MainWindow _mainWindow;
private void ShowLogin()
{
_mainWindow = new MainWindow(delegate()
{
//.......
});
_mainWindow.Closed += new EventHandler(_mainWindow_Closed);
this.MainWindow = _mainWindow;
this.MainWindow.Show();
}
As per my understanding you can programatically trigger click event once inside constructor .
How about LoginForm.Activate() after the splash screen is closed and the LoginForm is displayed?
Maybe try to get focus on TextBox on that form. Login name for example.
I think OnInitialized event may be too early. OnShown should be good.
Are you using Visual Studio? I know if you go to the form properties under the project tab, you can specify the start up object. Perhaps you can specify your main form and the splashscreen can load in front of it.
have you tried:
protected override void OnInitialized(EventArgs e)
{
while (this.CanFocus) { this.Focus(); WPFWaitForPriority.WaitForPriority(DispatcherPriority.Background); }
base.OnInitialized(e);
}

Categories

Resources