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

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.

Related

MainWindow gets closed when closing ChildWindow

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!

How to update the content of wpf listbox from different window

I've two windows: Main Window, Log Window. How can I update the listbox in the Log Window when some action is happened in the Main Window (e.g. button is clicked)?
Below is the code for listbox in Log Window:
<ListBox x:Name="DebugLogLb" BorderBrush="{x:Null}">
<TextBlock x:Name="DebugLogTb" Text="{Binding LogText}" Background="{x:Null}" />
</ListBox>
When the button in the Main Window is clicked, it will update the listbox. I tried with the code below but it doesn't work.
private void Btn1_Click(object sender, RoutedEventArgs e)
{
var log = new LogWindow();
log.DebugLogLb.Items.Add(new { LogText = "Button 1 is clicked" });
}
I'm able to update the listbox if I put everything in the same window, but I failed to do so with two windows.
My expected output would be like:
Even if both windows are opened, when the buttons in the Main Window are clicked, it will directly update in the Log Window as well.
Thanks for any helps in advanced.
It's hard to tell where you are going wrong without seeing more of the code. This is an example that works. It creates a new LogWindow in the MainWindow ctor and sets the DataContext. When the button is clicked the handler calls show on the window. The ListBox's itemssource property is bound to an ObservableCollection of strings. So any adds/removes are automatically updated on the UI.
LogWindows xaml
<Window x:Class="WpfApplication7.LogWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="LogWindow" Height="300" Width="300">
<Grid>
<ListBox x:Name="DebugLogLb" BorderBrush="{x:Null}" ItemsSource="{Binding LogText}" />
</Grid>
MainWindow code-behind
public partial class MainWindow : Window
{
LogWindow _logWindow;
public MainWindow()
{
InitializeComponent();
LogText = new ObservableCollection<string>();
_logWindow = new LogWindow();
_logWindow.DataContext = this;
_logWindow.Closed += _logWindow_Closed;
}
private void _logWindow_Closed(object sender, EventArgs e)
{
_logWindow = new LogWindow();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
_logWindow.Show();
LogText.Add("Button1 Clicked");
}
public ObservableCollection<string> LogText { get; set; }
}

Accessing original overwritten variable

I have WPF window code and I want to change the window title, normally i can do
this.Title = "Bla"
But what if in xaml part of the window code, I have a text box named Title (Name="Title") which overrides the default window Title variable which sets the title of the window? How do I access the original window title variable without having to rename the textbox?
First solution.
You can use base keyword:
base.Title = "bla";
Second solution.
You can change window title in the Loaded event, by casting sender object to Window.
XAML:
<Window x:Class="WpfWindow.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="title" Height="350" Width="525"
Loaded="Window_Loaded">
<Grid>
<TextBox Name="Title" MinWidth="100" />
</Grid>
</Window>
Code-behind:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
(sender as Window).Title = "bla";
}
}

How to display a PictureBox from behind code in C#

I know my question sounds basic, but i searched all over the place and found nothing..
this is my code :
public MainWindow()
{
InitializeComponent();
Map newMap = new Map();
newMap.setMapStrategy(new SmallMapStrategy());
newMap.createMap();
System.Windows.Forms.PictureBox pictureBox1 = new System.Windows.Forms.PictureBox();
pictureBox1.Paint += new System.Windows.Forms.PaintEventHandler(newMap.grid[3].afficher);
}
this is the afficher function :
public override void afficher(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(squareImage, pos_x, pos_y, 50, 50);
}
squareImage is an attribute corresponding to a Drawing.Image.
pos_x and pos_y are custom int32 attributes.
What i'd like is to SEE the image while running my application...
Since the PictureBox that you are using is a Winforms Control you will need to add a WindowsFormsHost Control to your Wpf Form and add the PictureBox to that. Any time you dynamically create a control you need to add it to the Form or Container object otherwise it will not be shown.
But first, add these references:
System.Windows.Forms
WindowsFormsIntegration
Now write code something like this.
MainWindow.xaml
<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>
<WindowsFormsHost Height="175" HorizontalAlignment="Left" Margin="10,10,0,0" Name="windowsFormsHost1" VerticalAlignment="Top" Width="255" />
</Grid>
</Window>
MainWindow.xaml.cs
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
System.Windows.Forms.PictureBox picturebox1 = new System.Windows.Forms.PictureBox();
windowsFormsHost1.Child = picturebox1;
picturebox1.Paint += new System.Windows.Forms.PaintEventHandler(picturebox1_Paint);
}
void picturebox1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(#"C:\Temp\test.jpg");
System.Drawing.Point ulPoint = new System.Drawing.Point(0, 0);
e.Graphics.DrawImage(bmp,ulPoint);
}
}
}

How to correctly implement a modal dialog on top a non-modal dialog?

In a WPF application I would like to implement the following behaviour which doesn't seem to work straightforward:
From the main window (Window1) the user opens a non-modal window (Window2), and that non-modal window may display a modal dialog (Window3).
The problem is that whenever the modal dialog has been shown, the main window disappears in the background (given that there are windows of other applications open) when the user closes the dialogs.
Is there anything wrong in the way that I use Window.Owner and Window.Show()/Window.ShowDialog(), is it a bug or is it something simply not supported?
The following simple WPF application demonstrates this behavior:
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Window2 win = new Window2();
win.Owner = this;
win.Show();
}
}
public partial class Window2 : Window
{
public Window2()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Window3 win = new Window3();
win.Owner = this;
win.ShowDialog();
}
private void btnClose_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}
public partial class Window3 : Window
{
public Window3()
{
InitializeComponent();
}
private void btnClose_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}
XAML Window1:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1">
<Button Click="Button_Click">Show non-modal window</Button>
</Window>
XAML Window2:
<Window x:Class="WpfApplication1.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window2">
<StackPanel>
<Button Click="Button_Click">Show modal dialog</Button>
<Button Name="btnClose" Click="btnClose_Click">Close</Button>
</StackPanel>
</Window>
XAML Window3:
<Window x:Class="WpfApplication1.Window3"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window3">
<Button Name="btnClose" Click="btnClose_Click">Close</Button>
</Window>
UPDATE: Fixed copy&paste error in the code. This is .NET 3.5 SP1 in case it matters.
Microsoft confirms this as a bug in WPF:
This isn't a regression from previous releases so it doesn't make the bar to be fixed for this version of the product. We'll look into this for a future release.
In the meantime, this can be worked around by activating the owner window when the child window is closing.
Sample code:
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void NonModalButtonClick(object sender, RoutedEventArgs e)
{
new Window1 { Owner = this }.Show();
}
private void ModalButtonClick(object sender, RoutedEventArgs e)
{
new Window1 { Owner = this }.ShowDialog();
}
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
if (this.Owner != null)
{
this.Owner.Activate();
}
}
}
(Note that the workaround will always bring the main window into foreground which might be different than the expected behavior)

Categories

Resources