Weird Unload Behaviour - WPF Window - c#

I have a simple WPF application with a MainWindow. Set up an unloaded event in the code behind. Set the MainWindow as the startup uri. Unloaded is not triggered when the window is closed. Create a second window - NotMainWindow with a single button click.
In the button click event, call MainWindow. Close MainWindow and unloaded is triggered. Why the difference in behaviour? What I am trying to get at is, how do I get some kind of unloaded event every single time?
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" Unloaded="Main_Unloaded">
<Grid>
</Grid>
</Window>
private void Main_Unloaded(object sender, RoutedEventArgs e)
{
}
<Window x:Class="WpfApplication2.NotMainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="NotMainWindow" Height="300" Width="300">
<Grid>
<Button Content="Show Main" Height="25" Margin="10" Width="70" Click="Button_Click" />
</Grid>
</Window>
private void Button_Click(object sender, RoutedEventArgs e)
{
MainWindow win = new MainWindow();
win.Show();
}
<Application x:Class="WpfApplication2.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="NotMainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>

Based on your comments I understand the scenario you're talking about. This is a known issue that unloaded is not called when shutting down the application (e.g. last window is closed).
If you just want to know when the window is closed use the Closing event:
public MainWindow()
{
this.Closing += new CancelEventHandler(MainWindow_Closing);
InitializeComponent();
}
void MainWindow_Closing(object sender, CancelEventArgs e)
{
// Closing logic here.
}
If you want to know when the last window is closed, e.g. your application is shutting down, you should use ShutdownStarted
public MainWindow()
{
this.Dispatcher.ShutdownStarted += Dispatcher_ShutdownStarted;
InitializeComponent();
}
private void Dispatcher_ShutdownStarted( object sender, EventArgs e )
{
//do what you want to do on app shutdown
}

Related

WPF ignore clicks outside of popup

In my WPF app I want to show a popup when I click a button.
If I click outside the popup, I want the popup to be closed. I can accomplish this by setting StaysOpen=False on the popup.
But when I click outside the popup, I want WPF to ignore the initial click that closes the popup. For example, if I click outside the popup on another button, I don't want that button to execute the click method.
How can I make WPF ignore the click outside the popup while it's open?
Here is some sample code. The popup opens when I click the "Popup" button, and it closes when I click outside. But I can click the "PrintMessage" button while the popup is open and its click event will fire. I would like its click event not to fire.
<Window x:Class="Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Popup x:Key="pop" StaysOpen="False" Placement="MousePoint">
<UniformGrid Background="Red">
<Button>Btn1</Button>
<Button>Btn2</Button>
</UniformGrid>
</Popup>
</Window.Resources>
<UniformGrid>
<Button Click="Popup_Click">Popup</Button>
<Button Click="PrintMessage_Click">PrintMessage</Button>
</UniformGrid>
</Window>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Popup_Click(object sender, RoutedEventArgs e)
{
Popup pop = (Popup)Resources["pop"];
pop.IsOpen = true;
}
private void PrintMessage_Click(object sender, RoutedEventArgs e)
{
Debug.WriteLine("Test");
}
}

Navigating to another XAML file

I have three XAML files, they are mainwindow.xaml,login.xaml,homepage.xaml. Since the files can be navigated through frames, i added a frame to main window which fits the whole screen.
XAML of MainWindow:
<Window x:Class="Myproject.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" WindowState="Maximized" Initialized="Window_Initialized">
<Grid>
<Frame Name="pageFrame"></Frame>
</Grid>
</Window>
CS file of MainWindow:
private void Window_Initialized(object sender, EventArgs e)
{
pageFrame.Height = SystemParameters.WorkArea.Height-10;
pageFrame.Width = SystemParameters.WorkArea.Width;
pageFrame.Navigate(new login());
}
It navigates perfectly to login page and perform login actions there.
The problem is it does not navigate to the homepage.xaml from the login.xaml.cs
Code used for navigating to homepage.xaml from login.xaml.cs
MainWindow mw = new MainWindow();
mw.pageFrame.Navigate(new homepage());
This code goes in a if statement section and i checked by using breakpoints if these statements are executed. And it does execute those and the objects are populated but the naviagtion does not occur.
What am i doing wrong? Is this not the correct approach?
The problem is, well, mw is a new window and it is not even shown at all. And you are staying in your old instance of MainWindow, nothing happens to your old MainWindow.
You need to navigate from within your old MainWindow, not a new one.
((MainWindow)(Application.Current.MainWindow)).pageFrame.Navigate(new homepage());
You have a reference to your main window, Application.Current.MainWindow, but you need to cast it into your own type of MainWindow first.

Textbox created in WPF is not editable at run time

I am creating a WPF Window in which I have text boxes. However, when I run the project in Debug mode, (F5), I am not able to edit the text boxes that I created, nor am I able to choose from the listbox that I created. I googled, found that WPF and Win32 need to communicate to accept keyboard input, and got these 3 lines :
Window w = new Window1();
System.Windows.Forms.Integration.ElementHost.EnableModelessKeyboardInterop(w);
w.Show();
However, I am new to C# and hence I have absolutely no idea where to insert this C# code. I added the System.Windows.Forms and WindowsFormIntegration references to my project.
The window I am designing will be the first window that will appear at the launch of the application, hence I need the textboxes in this window to be editable without launching another window. Kindly guide me.
Edit : This is my XAML code:
<Window x:Name="Window1" x:Class="Myproject.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Risk Assessment"
Height="741" Width="1216.091">
<GroupBox x:Name="GroupBox1">
<Grid>
<TextBox x:Name="Length" IsReadOnly ="False" IsEnabled="True" />
</Grid>
</GroupBox>
</Window>
This is my C# code:
namespace Myproject
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
}
Edit 2: I modified the first line in the App.Xaml code like this :
<Application x:Class="Myproject.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Startup="Application_Startup">
And in the App.Xaml.cs I added this snippet:
private void Application_Startup(object sender, StartupEventArgs e)
{
MainWindow win = new MainWindow();
ElementHost.EnableModelessKeyboardInterop(win);
win.Show();
System.Windows.Threading.Dispatcher.Run();
}
But still no luck. Where am I going wrong?
Try to change your Application.xaml to include the StartupUri:
<Application x:Class="Myproject.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Window1.xaml"
>
Remove all the startup code you had in the cs file.
Or
Change your cs code to this:
Window1 window1 = new Window1();
this.ShutdownMode = ShutdownMode.OnMainWindowClose;
this.MainWindow = window1;

ShowDialog in WPF

When I make two calls for ShowDialog in WPF the first window open normally, after closing it the second one doesn't appear.
<Application
x:Class="Test.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Startup="App_OnStartup">
</Application>
private void App_OnStartup(object sender, StartupEventArgs e)
{
var windowA = new WindowA();
windowA.ShowDialog();
var windowB = new WindowB();
windowB.ShowDialog();
}
WindowA:
<Window x:Class="Test.WindowA"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WindowA" Height="129.452" Width="313.356">
<Grid>
<Button Content="Button" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Margin="139,54,0,0"/>
</Grid>
</Window>
public partial class WindowA : Window
{
public WindowA()
{
InitializeComponent();
}
}
WindowB:
<Window x:Class="Test.WindowB"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WindowB" Height="221.918" Width="300">
<Grid>
<RadioButton Content="RadioButton" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="124,63,0,0"/>
</Grid>
</Window>
public partial class WindowB : Window
{
public WindowB()
{
InitializeComponent();
}
}
In WPF you can specify when application shuts down and by default Application.ShutdownMode is OnLastWindowClose which means that when last Window is closed applications shuts down and in your case first Window is also last. When you open and close first Window your application shuts down and that's why you don't see second Window. You would need to change ShutdownMode to OnExplicitShutdown
<Application ... ShutdownMode="OnExplicitShutdown"/>
but this means that even when you close all your windows application is still running so you have to explicitly call Application.Shutdown() to shutdown your application, for example when main window is closed.
ShowDialog() function invokes the window modally. Which means code after windowA.ShowDialog(); will not execute until that window is closed.

WPF Close button not working when in Grid

When I place Button in grid and add to is's click action:
this.Close();
It's not working. I want to be able to ask user before exit so I want to use Close(). I don't want to use Application.Shutdown();
How to solve it.
Just tested it and it works fine! I created a new WPF application and a basic window:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button Content="Close" x:Name="closeButton" Click="closeButton_Click" />
</Grid>
</Window>
and then added the following to the code-behind
private void closeButton_Click(object sender, RoutedEventArgs e)
{
if (MessageBox.Show("Are you sure?", "Application", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{
this.Close();
}
}
And it works 100%... Can you post more code to see if something else is wrong? What .NET version are you using, etc...

Categories

Resources