Close page within Frame in a WPF - c#

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();
}
}

Related

When Form1 loads, hide it and show Form2

Been stuck for quite a while reading similar posts here, I did find a solution but it was in dummy code and I just don't know what I'm doing wrong.
I have 2 forms, when the main form loads up I want to hide it and show form2 (the login form)
code looks like this.
private void Form1_Load(object sender, EventArgs e)
{
login loginform = new login();
loginform.Show();
this.Hide();
}
But when I run the program both forms are open and visible.
What am I doing wrong? Shouldn't the main form be hidden?
The Hide method does not have any effect from the Load event, since there isn't a handle created yet.
You have two options:
Using the Shown event (or better, the HandleCreated event) and hide it if a condition is met (like a variable 'logon form not shown')
Show the logon form as start form, then open the 'main' form. You can do this by passing an ApplicationContext around and pass on control to the main form.
You can do it with help of owner property, here is working example
Main form
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
var loginFormMax = new LoginFormMax { Owner = this };//save main form as owner inside child form
loginFormMax.Show();
}
}
Child Form
public partial class LoginFormMax : Form
{
public LoginFormMax()
{
InitializeComponent();
}
private void LoginFormMax_Shown(object sender, EventArgs e)
{
var owner = this.Owner;
owner.Hide();//now you have control over owner form, just hide it
}
private void LoginFormMax_FormClosing(object sender, FormClosingEventArgs e)
{
var owner = this.Owner;
owner.Show();//now you have control over owner form, just show it again
}
}

Open LoginWindow before MainWindow?

I've tried using the answer found on this thread Show login before MainWindow, but changing the shut down parameters causes issues in my application.
What is classes as the best practice for this in WPF?
I did not test this, but this should work.
private void Application_Startup(object sender, StartupEventArgs e)
{
LoginFRM f = new LoginFRM();
MainWindow mainWindow = new MainWindow();
f.Loaded += (sender, e) =>
{
Application.Current.MainWindow = mainWindow();
};
if (f.ShowDialog() == true)
{
mainWindow.show();
}
}
Basically, the program would close if the window Application.Current.MainWindow is pointing closes. The first window instantiated is assigned to this property, so you should manually set this property to your own mainwindow, after the login window is being instantiated. Read more from here.
Edit
After some thoughts, it's probably better to do it this way:
// In App.xaml.cs:
private void Application_Startup(object sender, StartupEventArgs e)
{
LoginWindow loginWindow = new LoginWindow();
loginWindow.ShowDialog();
}
// In LoginWindow.xaml.cs
public LoginWindow()
{
InitializeComponent();
this.Closed += LoginWindow_Closed;
}
protected void LoginWindow_Closed(object sender, EventArgs e)
{
if (this.UserIsAuthenticated)
{
MainWindow mainWindow = new MainWindow();
Application.Current.MainWindow = mainWindow;
mainWindow.Show();
}
}
Most likely your LoginWindow is the main window of your application - that's the case if it is the first window opened in your application (which is automatically assigned as the application's main window). The application is by default configured to shut down if the main window is closed. So if you don't want to alter that configuration, your other option is to replace application's main window once you're ready to show the actual main window and before you close the login window. Here's an example method accomplishing this task:
void ShowMainWindow()
{
var mainWindow = new MainWindow();
Application.Current.MainWindow = mainWindow;
mainWindow.Show();
//I assume loginWindow is a reference to the LoginWindow being shown
loginWindow.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();
}

WPF - C# - open parent window only once

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)

MouseDown event on new Window does not DragMove MainWindow

I have a WPF application that I have removed the border and default controls by doing the following:
WindowStyle="None" AllowsTransparency="True"
Now I added a MouseDown handler MouseDown="Window_MouseDown" and added the following code to allow me to move my Window around:
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
try
{
if (e.ChangedButton == MouseButton.Left)
DragMove();
}
catch (Exception ex) { }
}
But now I have a UserControl that I want to resize to the full size of my Application so to achieve this I created a new Window that is the same size as my MainWindow and placed the UserControl onto it. I create this new Window and set its parent to be my main application like so:
public MyFullScreenWindow()
{
InitializeComponent();
this.Owner = App.Current.MainWindow;
}
I launch this window like so:
MyFullScreenWindow fullScreen = new MyFullScreenWindow();
fullScreenVideo.ShowDialog();
My problem is that I want to still move my whole application around whenever the user clicks and moves this new window. To achieve this I have added an Event to MyFullScreenWindow:
public partial class MyFullScreenWindow: Window
{
static public event EventHandler MouseDownEvent;
public MyFullScreenWindow()
{
InitializeComponent();
this.Owner = App.Current.MainWindow;
}
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
if (MouseDownEvent != null)
{
MouseDownEvent(sender, e);
}
}
}
And I handle this event in my MainWindow like so:
MyFullScreenWindow.MouseDownEvent += new EventHandler(MyFullScreenMouseDownHandler);
private void MyFullScreenMouseDownHandler(object sender, EventArgs e)
{
DragMove();
}
But when I click and drag I see that the event is fired off but my whole application does not move like it should. Why is this??
Simply add the following function code only
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
// Begin dragging the window
this.DragMove();
}
move your window where ever you want.
I don't know the context of your problem, but why would you create a new window, "place" it inside the parent one? You can use controls without creating a new window.
It's possible that you are doing this because you need AllowTransparency=false functionality, while showing it in AllowTransparency=true window. (I had this case when working with DirectShow). If you're doing this for custom window chrome, then don't use AllowTransparency - it decreases performance greatly. It's creating picture of every frame and disables GPU acceleration, after all! Instead, you can adapt to CustomChromeWindow project(found on Internets).
Note that you can enable the main window so that it would process messages from underlying window:
public class WindowSecond : Window
{
public WindowSecond()
{
Owner = Application.Current.MainWindow;
MouseDown += delegate
{
// maybe cache it.
IntPtr handle = new WindowInteropHelper(Owner).Handle;
EnableWindow(handle, true);
Application.Current.MainWindow.DragMove();
EnableWindow(handle, false);
};
}
[DllImport("user32")]
internal static extern bool EnableWindow(IntPtr hwnd, bool bEnable);
}

Categories