MainWindow gets closed when closing ChildWindow - c#

I am developing a wpf application for the surface pro in tablet mode. I am coding on a different computer and there everything works fine. When testing the application on the surface pro something weird happens:
During the application a second window gets opened, in order to modify some settings. This window includes a button in order to close the window (see code below). When this button is clicked on the surface pro the whole application gets closed (including the main window). On the computer where I am writing the code this never happens, so in my opinion the problem lies with the hardware.
Thank you for your help!
Edit 21/03/2018
So as discussed in the comments I have tried several things and the problem remains. I have now deleted most of the application code such that only the essential feature remain and the problem still hasn't disappeared. I will post the code below:
App.xaml
<Application x:Class="TestNamespace.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestNamespace"
Startup="ApplicationStartup">
<Application.Resources>
<Style TargetType="{x:Type Window}">
<Setter Property="FontFamily" Value="Segoe UI" />
</Style>
</Application.Resources>
</Application>
App.xaml.cs
public partial class App : Application
{
public MainWindow window = new MainWindow();
public Monitoring monitoring;
private void ApplicationStartup(object sender, StartupEventArgs e)
{
window.Show();
monitoring = new Monitoring();
window.Content = monitoring.gui;
this.DispatcherUnhandledException += App_DispatcherUnhandledException;
this.Dispatcher.UnhandledException += Dispatcher_UnhandledException;
}
private void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
System.Diagnostics.Debug.WriteLine("App1: There has been an unhandled exception");
throw new NotImplementedException();
}
private void Dispatcher_UnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
System.Diagnostics.Debug.WriteLine("App2: There has been an unhandled exception");
throw new NotImplementedException();
}
}
GUI.xaml
<UserControl x:Class="TestNamespace.GUI"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:oxy="http://oxyplot.org/wpf"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:mi="http://schemas.microsoft.com/expression/2010/interactions"
xmlns:local="clr-namespace:TestNamespace">
<Grid Background="Black">
<Button HorizontalAlignment="Center" VerticalAlignment="Center"
Width="300" Height="300"
Content="NewWindow" Click="SettingsButton_Click"/>
</Grid>
</UserControl>
GUI.xaml.cs
public partial class GUI : UserControl
{
private Monitoring monitoring;
public GUI(Monitoring monitoring)
{
this.monitoring = monitoring;
InitializeComponent();
this.Dispatcher.UnhandledException += Dispatcher_UnhandledException;
}
private void Dispatcher_UnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
System.Diagnostics.Debug.WriteLine(" GUI: There has been an unhandled exception");
throw new NotImplementedException();
}
private void SettingsButton_Click(object sender, RoutedEventArgs e)
{
monitoring.settingsWindow = new testWindow();
monitoring.settingsWindow.Show();
}
}
Monitoring.cs
public class Monitoring
{
private App currentApp = (App)Application.Current;
public GUI gui;
public Window settingsWindow;
public Monitoring()
{
gui = new GUI(this);
}
}
TestWindow.xaml
<Window x:Class="TestNamespace.testWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TestNamespace"
mc:Ignorable="d"
Title="testWindow"
ResizeMode="NoResize" WindowState="Maximized" WindowStyle="None">
<Grid>
<Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="245,200,0,0" VerticalAlignment="Top" Width="75" Click="button_Click"/>
</Grid>
</Window>
TestWindow.xaml.cs
public partial class testWindow : Window
{
public testWindow()
{
InitializeComponent();
this.Dispatcher.UnhandledException += Dispatcher_UnhandledException;
}
private void Dispatcher_UnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
System.Diagnostics.Debug.WriteLine("TestWindow: There has been an unhandled exception");
throw new NotImplementedException();
}
private void button_Click(object sender, RoutedEventArgs e)
{
e.Handled = true;
this.Close();
}
}
MainWindow.xaml
<Window x:Class="TestNamespace.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:TestNamespace"
mc:Ignorable="d"
ResizeMode="NoResize" WindowStartupLocation="CenterScreen" WindowState="Maximized" WindowStyle="None">
<Grid Background="White">
<TextBox x:Name="textBox" HorizontalAlignment="Center" Height="47" TextWrapping="Wrap" Text="LOADING..." VerticalAlignment="Center" Width="198" FontWeight="Bold" FontSize="36" BorderBrush="{x:Null}" />
</Grid>
</Window>
MainWindow.xaml.cs
partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
This is the complete code for the Minimal, Complete, and Verifiable example. This code still produces the error on the tablet. Thank you for your help!

I finally managed to solve the problem! Instead of creating and showing a new window, I created a new UserControl (TestWindow) and changed the content of the mainWindow. Upon closing the TestWindow, the normal GUI is loaded as Content of the MainWindow and the TestWindow is set to null.
It might not be the best solution, but it works.
EDIT 1
A few weeks later I stumbled upon the same problem once again. I found a solution written by Erti-Chris Eelmaa that finally solved the problem. I needed to change the Application.ShutdownMode such that the application only shuts down when Application.Shutdown(); is explicitly called.
Application.ShutdownMode = ShutdownMode.OnExplicitShutdown;
I hope this helps!

Related

Navigating with "Enter" focuses Button on other page

I have one "login page" and one "content page". The login page consists of a PasswordBox and a Button. When the button is clicked or the Enter-key is pressed in the PasswordBox, I want the program to navigate to the next page. Navigating with the button works fine, but when the page is changed due to the pressed enter key, the Button on the next page is focused. How can I disable/avoid this behaviour?
"Focused" button:
MainPage.xaml
<Page
x:Class="TabNavigation.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TabNavigation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
<StackPanel>
<PasswordBox x:Name="textBox" KeyDown="HandleTextBox_KeyDown"/>
<Button x:Name="loginButton" Content="Einloggen" Click="HandleLoginButton_Click"/>
</StackPanel>
</Grid>
</Page>
MainPage.xaml.cs
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
namespace TabNavigation {
public sealed partial class MainPage : Page {
public MainPage() {
this.InitializeComponent();
}
private void HandleTextBox_KeyDown(object sender, KeyRoutedEventArgs e) {
if(e.Key == Windows.System.VirtualKey.Enter) {
this.Frame.Navigate(typeof(ContentPage));
}
}
private void HandleLoginButton_Click(object sender, RoutedEventArgs e) {
this.Frame.Navigate(typeof(ContentPage));
}
}
}
ContentPage.xaml
<Page
x:Class="TabNavigation.ContentPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TabNavigation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
<StackPanel>
<Button>Test</Button>
</StackPanel>
</Grid>
</Page>
You can cancel the focus in GettingFocus:
<Button GettingFocus="Button_GettingFocus">Test</Button>
private void Button_GettingFocus(UIElement sender, GettingFocusEventArgs args)
{
args.Cancel = true;
}
Old answer:
You have few options:
Disable focus on button with IsTabStop=false
Change TabIndex to larger integer than other elements.
Set focus from your code to something else: otherControl.Focus(FocusState.Programmatic);

Is there a way to change the size and style of a host window from a navigationpage? (WPF)

I have a host window that has a page as follows:
<Window x:Class="myAPP.filesXAML.WinModel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:myApp.filesXAML"
mc:Ignorable="d"
WindowStartupLocation="CenterScreen"
ResizeMode="NoResize"
WindowStyle="None"
Title="myAPP" Height="562" Width="1000">
<Grid>
<Frame NavigationUIVisibility="Hidden" Source="/filesXAML/Login.xaml" Background ="White"/>
</Grid>
</Window>
Then in the code in C# I call another page as follows:
NavigationService.Navigate(new Uri("filesXAML/UserPage.xaml", UriKind.Relative));
At this point I want to change the size and style of the host window.
Is there a way to do it?
Any suggestions or comments are welcome.
You can use the following code to change the size of MainWindow in Page
public partial class Page1 : Page
{
public Page1()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Application.Current.Windows[0].Width = 100;
Application.Current.Windows[0].Height = 100;
}
}

checkbox checked or click event not firing in datatemplate

I have a checkbox in my datatemplate and for some reason the events are not firing. see code below. my datatemplate is in a resource dictionary with code behind file. Any Ideas?
<ResourceDictionary x:Class="ArmyBuilder.Templates.EquipmentDataTemplate"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<DataTemplate x:Key="EquipmentDataTemplate">
<Grid>
<CheckBox Content="{Binding Name}" Checked="ToggleButton_OnChecked" Click="CheckBox_Click"/>
</Grid>
</DataTemplate>
//code behind
namespace ArmyBuilder.Templates
{
public partial class EquipmentDataTemplate : ResourceDictionary
{
public EquipmentDataTemplate()
{
InitializeComponent();
}
private void ToggleButton_OnChecked(object sender, RoutedEventArgs e)
{
// breakpoint not hit
}
private void CheckBox_Click(object sender, RoutedEventArgs e)
{
// breakpoint not hit
}
}
}
I am not sure how you use it, but the your code works for me and the click event got fired. Check the following and if you still cannot find the point, share a repro project to show how you used it.
Template XAML:
<ResourceDictionary x:Class="App10.EquipmentDataTemplate"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<DataTemplate x:Key="EquipmentDataTemplate">
<Grid>
<CheckBox Content="Click Me" Checked="ToggleButton_OnChecked" Click="CheckBox_Click"/>
</Grid>
</DataTemplate>
</ResourceDictionary>
Template cs:
namespace App10
{
public sealed partial class EquipmentDataTemplate : ResourceDictionary
{
public EquipmentDataTemplate()
{
this.InitializeComponent();
}
private void ToggleButton_OnChecked(object sender, RoutedEventArgs e)
{
// breakpoint not hit
}
private void CheckBox_Click(object sender, RoutedEventArgs e)
{
// breakpoint not hit
}
}
}
In MainPage.Xaml, use the template in a ListView:
<Page
x:Class="App10.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App10"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.Resources>
<local:EquipmentDataTemplate></local:EquipmentDataTemplate>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ListView x:Name="listView" CanReorderItems="True" AllowDrop="True" ItemTemplate="{StaticResource EquipmentDataTemplate}">
</ListView>
</Grid>
</Page>
In MainPage cs:
namespace App10
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
var list = new ObservableCollection<string>();
for (int i = 0; i < 10; i++)
{
list.Add("Item " + i);
}
listView.ItemsSource = list;
}
}
}

How to open the same instance of a previously closed window?

I implemented the control basics sample from the Kinect for Windows toolkit http://msdn.microsoft.com/en-us/library/dn188701.aspx to control the cursor with a users hand, but when I click on a sub window and then re open the main window with the hand cursor doesn't show.
My question is how do I open a new window without closing the previous window and then navigate back to the same instance of that window, not a new instance?
This is how I call a new window in my main window class:
private void trainingBtn_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.
}
And this is how I reopen the main window, but it creates anew instance of the main window which I don't want.
private void homeBtn_Click(object sender, RoutedEventArgs e)
{
var newForm = new MainWindow(); //create your new form.
newForm.Show(); //show the new form.
this.Close(); //only if you want to close the current form.
}
What you need is composition
Here how it should look your mainWindow class
public partial class MainWindow : Window
{
private trainingWindow _trainingWindow;
public MainWindow()
{
InitializeComponent();
}
private void buttonGoTraining_Click(object sender, RoutedEventArgs e)
{
if (_trainingWindow== null)
{
_trainingWindow= new trainingWindow(this);
}
this.Visibility = Visibility.Hidden;
_trainingWindow.Show();
_trainingWindow.Visibility = Visibility.Visible;
this.Visibility = Visibility.Hidden;
}
}
and here is your training class
public partial class trainingWindow : Window
{
private MainWindow _mainWindow;
public trainingWindow(MainWindow mainWindow )
{
InitializeComponent();
_mainWindow = mainWindow;
}
private void biuttonBack_Click(object sender, RoutedEventArgs e)
{
this.Visibility = Visibility.Hidden;
_mainWindow.Visibility = Visibility.Visible;
}
}
here is the xaml
<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">
<Grid>
<Button Content="Button" Height="121" HorizontalAlignment="Left" Margin="112,38,0,0" Name="button1" VerticalAlignment="Top" Width="195" Click="buttonGoTraining_Click" />
</Grid>
</Window>
<Window x:Class="WpfApplication2.trainingWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="trainingWindow" Height="300" Width="300">
<Grid>
<Button Content="Button" Height="36" HorizontalAlignment="Left" Margin="52,33,0,0" Name="button1" VerticalAlignment="Top" Width="97" Click="biuttonBack_Click" />
</Grid>
</Window>
Simply hide it, and not close.
If you need to show a fresh information after show, just bind a new data to its view model.

When to clean up a command-binded control?

I have a user control which has a CheckBox, a Button, and a CommandBinding. If the CheckBox is checked, the Button is enabled. The MainWindow uses the UserControl. When the Button in the main window is pressed, the UserControl is removed from UI, and GC.Collect() is called, but CanExecute method still runs.
I find that if I click the button in main window twice, CanExecute will no longer run. It seems that I don't call GC.Collect() at the right time.
I want to know what is the good timing to call GC to clean the unused user control, so that CanExecute will not be called.
XAML
<UserControl x:Class="WpfApplication1.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<RoutedUICommand x:Key="okCommand" Text="OK"/>
</UserControl.Resources>
<UserControl.CommandBindings>
<CommandBinding Command="{StaticResource okCommand}" CanExecute="CommandBinding_CanExecute_1"/>
</UserControl.CommandBindings>
<StackPanel>
<CheckBox Name="checkBox" Content="CheckBox"/>
<Button Command="{StaticResource okCommand}" Content="{Binding Path=Text, Source={StaticResource okCommand}}"/>
</StackPanel>
</UserControl>
Code behind
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
private void CommandBinding_CanExecute_1(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = checkBox.IsChecked.GetValueOrDefault(false);
System.Media.SystemSounds.Beep.Play();
}
}
MainWindow
<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" Loaded="Window_Loaded_1">
<StackPanel>
<Border Name="container"/>
<Button Content="Set Null" Click="Button_Click_1"/>
</StackPanel>
</Window>
Code behind
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
container.Child = null;
GC.Collect();
GC.WaitForPendingFinalizers();
}
private void Window_Loaded_1(object sender, RoutedEventArgs e)
{
UserControl1 uc = new UserControl1();
container.Child = uc;
}
}
Use grid as container and Container.Clear() method and forget about GC.
I find another solution. That is to call CommandBindings.Clear() in UserControl1 when it unloads.
I believe this is a neat way, since the caller of UserControl1 doesn't take care of the cleaning job of UserControl1.

Categories

Resources