WPF - C# - open parent window only once - c#

I´m programming a simple thing in C# and WPF. I have a MainWindow with a button. If I trigger the button it opens a secon window:
private void btnF4_Click(object sender, RoutedEventArgs e)
{
SecondWindow second = new SecondWindow();
second.Show();
}
Naturally if I trigger the button three or four times, I have three or four windows open. I don´t want to use ShowDialog(), but I want to open my second window only once. I mean if I trigger the button and the window is already open, should nothing happen.
Thank you!

Make second an instance variable to the parent window class and only create a new window if it hasn't been created.
Of course you need to make sure to null the instance variable when the second window is closed.
public class ParentWindow ...
{
private SecondWindow m_secondWindow = null;
....
private void btnF4_Click(object sender, RoutedEventArgs e)
{
if (m_secondWindow == null)
{
m_secondWindow = new SecondWindow();
m_secondWindow.Closed += SecondWindowClosed;
m_secondWindow.Show();
}
}
public void SecondWindowClosed(object sender, System.EventArgs e)
{
m_secondWindow = null;
}
}
This might be shortened to the following:
public class ParentWindow ...
{
private SecondWindow m_secondWindow = null;
....
private void btnF4_Click(object sender, RoutedEventArgs e)
{
if (m_secondWindow == null)
{
m_secondWindow = new SecondWindow();
}
m_secondWindow.Show();
}
}
However, I'm never sure whether you can actually "reopen" a window that was closed before. If you need to initialize the window all over upon reopening, use the first code. If you can live with the window starting up showing the previous content, use the second.

Declare SecondWindow in Parent Window class instead of a method.
public class MainWindow : Window {
SecondWindow second = new SecondWindow();
private void btnF4_Click(object sender, RoutedEventArgs e) {
if (!second.IsActive) {
second.Show();
}
}
}
Declaring second in the method makes the second window local to the method, which means every time you click the button it will create a new instance of that class (window)

Related

how to show a window only one time?

I want display a window only one time. When the user click on this button:
private void Notification_Click(object sender, RoutedEventArgs e)
{
NotificationSettings notifications = new NotificationSettings();
notifications.ShowDialog();
}
this will create a new window, I want that if there is already a window opened the user can't open a new one. There is an option in xaml for tell to compiler this? I remember the vb.net with windows form that allow to set the option to show only one windows at time.
Thanks.
Just hold a reference to your window in a field/property and check if it's Visisble already.
well I am not sure what is NotificationSettings exactly but for a window you can create a bool flag to mark when the window is opened and closed, check this code:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
bool WindowFlag = false;
private void button_Click_1(object sender, RoutedEventArgs e)
{
Window TestWindows = new Window();
TestWindows.Closing += TestWindows_Closing;
if (WindowFlag == true)
{
MessageBox.Show("The Window is already opened");
}
else
{
TestWindows.Show();
WindowFlag = true;
}
}
private void TestWindows_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
WindowFlag = false;
}
}

Close page within Frame in a WPF

I have a window and a Frame within it. in that Frame, i open many pages which i would like to close by clicking on "Close" button ,
the problem is the page can't see my frame i tried to write in an event a close button in a page method
to execute another event in a main window because it's easy on a main window to see a frame , but it's not working. here is my code in a page
private void closebt_MouseDown(object sender, MouseButtonEventArgs e)
{
var main = new MainWindow();
main.Exitbt_PreviewKeyDown(main.Exitbt, e);
}
and here is a code in a main window
internal void Exitbt_PreviewKeyDown(object sender, MouseButtonEventArgs e)
{
ProjectorFrame.Content = "";
MessageBox.Show("done");
}
Although the message show but it's not close page
please help me.
I don't know why you create another MainWindow instance inside the closebt_MouseDown hander, but I hope the following code would helpful for you:
private void closebt_MouseDown(object sender, MouseButtonEventArgs e)
{
MainWindow main = Application.Current.MainWindow as MainWindow;
if (main != null)
{
main.Exitbt_PreviewKeyDown(main.Exitbt, e);
main.Close();
}
}
Edited:
I supposed that the main Window object of your application is MainWindow, so I thought that the previous code could get your application window close.
But as you commented, Application.Current.MainWindow is different from MainWindow, and the main became null.
Therefore, I think the simple way to get the main Window object is to create the following constructor in your page class to keep the reference:
class YourPageClass
{
public YourPageClass(MainWindow mainWindow)
{
main = mainWindow;
}
private MainWindow main;
(snip)
}
Then, create this instance with passing main Window object:
// somewhere in MainWindow code where instantiate your page object
var page = new YourPageClass(this);
By doing that, you can get the main Window object.
So now, you can close your Window object as follows:
// in YourPageClass code
private void closebt_MouseDown(object sender, MouseButtonEventArgs e)
{
if (main != null)
{
main.Exitbt_PreviewKeyDown(main.Exitbt, e);
main.Close();
}
}

C# form application moving from page to page

I am building a game. I have a Menu page, with a "Start" button. I would like to know how I can make the button direct the user to a new page with the game. I thought of simply changing all buttons' and labels' visibility to false, but that would be very messy. I thought of closing the form and reopening a new one as said here:
http://social.msdn.microsoft.com/Forums/windows/en-US/936c8ca3-0809-4ddb-890c-426521fe60f1/c-open-a-new-form-and-close-a-form?forum=winforms
Like this:
public static void ThreadProc()
{
Application.Run(new Form());
}
private void button1_Click(object sender, EventArgs e)
{
System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(ThreadProc));
t.Start();
this.Close();
}
but when I click the button, you can see the form closing and reopening again, and it doesn't even reopen at the same coordinates.
Is there any way to do such a thing? I want it to move from page to page as it would if this was a website. Is this possible? If so how? Thanks in advance :-)
Use UserControls for every view you need and then switch between them in your code by adding/removing them to/from your form.
Example: The start-page is a UserControl containing the button that starts the game. The game UI is another UserControl that contains all the logic and visuals for your game.
You could then use something like he following:
public class StartView : UserControl
{
...
private void btnStart_Click(object sender, EventArgs e)
{
// Raise a separate event upon the button being clicked
if (StartButtonPressed != null)
StartButtonPressed(this, EventArgs.Empty);
}
public event EventHandler<EventArgs> StartButtonPressed;
}
public class GameView : UserControl
{
...
}
public UserControl SwitchView(UserControl newView)
{
UserControl oldControl = null;
if (this.Controls.Count > 0)
{ oldControl = (UserControl)this.Controls[0];
this.Controls.RemoveAt(0);
}
this.Controls.Add(newView);
newView.Dock = DockStyle.Fill;
return oldControl;
}
You can now create the start view in Form_Load:
public void Form_Load(object sender, EventArgs e)
{
StartView v = new StartView();
v.StartButtonPressed += StartButtonPressed;
SwitchView(v);
}
The event handler that reacts to the start button being pressed would do this:
public void StartButtonPressed(object senderView, EventArgs e)
{
GameView v = new GameView();
UserControl old = SwitchView(v);
if (old != null)
old.Dispose();
}

Opening a view via another event

I have several views that need to be opened, but I don't want to repeat the code. Currently each button triggers something like this:
private void icon_Add(object sender, RoutedEventArgs e)
{
viewName var = new viewName();
var.Show();
Close();
}
Ideally, I'd like something like this (but don't know what type of variable/object I should use):
private void icon_Add(object sender, RoutedEventArgs e)
{
OpenView(viewName)
}
private voice OpenView(?????? newView)
{
newView var = new newView();
var.Show();
Close();
}
Any help would be appreciated (yet again).
You could solve it with Reflection by using Activator.CreateInstance.
private void icon_Add(object sender, RoutedEventArgs e)
{
OpenView(typeof(viewName));
}
private void OpenView(Type newView)
{
if(typeof(Window).IsAssignableFrom(newView)) {
Window window = (Window)Activator.CreateInstance(newView);
window.Show();
window.Close();
}
}
This means you'll pass the Type of Window you'd like to open to the OpenView method. This method creates an instance by using the default constructor. It will then call Show and Close on the created Window. The IF before all that is meant to check whether the passed Type is a Window.
It is also possible to pass constructor arguments to CreateInstance, in case you don't have a default constructor on every Window.
I hope that makes some sense.

getting System.ObjectDisposedException: Cannot access a disposed object.Modeless Dialogs in C#

I'd like to generate a modeless dialog box, whenever I close the box and want to open it again I am getting an error saying
System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'TransactionHistoryDialog'.
at System.Windows.Forms.Control.CreateHandle()
here is my code for creating the modeless dialogbox
public partial class TransactionHistoryDialog : Form
{
private static TransactionHistoryDialog instance;
private TransactionHistoryDialog()
{
InitializeComponent();
}
public static TransactionHistoryDialog CreateForm()
{
if (instance == null)
{
instance = new TransactionHistoryDialog();
}
return instance;
}
private void TransactionHistoryDialog_FormClosing(object sender, FormClosingEventArgs e)
{
instance = null;
}
private void buttonClose_Click(object sender, EventArgs e)
{
instance = null;
}
private void buttonTransactionHistoryClose_Click(object sender, EventArgs e)
{
this.Dispose();
}
}
then in my main form whenever the transactionHistory button is clicked transaction dialog shows up : here is my code for event of clicking transaction button
private void buttonTransferHistory_Click(object sender, EventArgs e)
{
TransactionHistoryDialog transactionHistory = TransactionHistoryDialog.CreateForm();
transactionHistory.updateTextBox();
transactionHistory.Show();
}
I have search a lot, but could not find where the problem is. can any one please give me some hints ?
Because closing the Window disposes it. You need to create a new one after it has closed, you cannot show the same Window after it has closed. If you want to show the same one don't close it and in a handler set Visibility to Hidden instead then add another method, e.g. UnHide(), set it back to Visible when wanting to show the same instance again.
I prefer just creating a new one:
TransactionHistoryDialog openTransactionHistoryDialog;
private void buttonTransferHistory_Click(object sender, EventArgs e)
{
if(openTransactionHistoryDialog == null)
{
openTransactionHistoryDialog = new TransactionHistoryDialog();
openTransactionHistoryDialog.updateTextBox();
openTransactionHistoryDialog.Closed += OnTransactionHistoryDialogClosed;
}
openTransactionHistoryDialog.Show();
}
private void OnTransactionHistoryDialogClosed(object sender, EventArgs e)
{
openTransactionHistoryDialog = null;
}
UPDATE: There is an "official" example of a modeless dialog box at the bottom of this page: http://msdn.microsoft.com/en-us/library/aa969773(v=vs.110).aspx.

Categories