I'm trying to tighten navigation in my WP8 app and I'm having an issue where I want to exit when the user is on the main xaml page (which could be navigated to from many pages within my app). The simplest way about it seemed to let the back button handle exiting, but in order to do this it seems you need to clear the back button's history so that it can exit.
MSDN says to use the NavigationService.RemoveBackEntry method to clear out back entries (and thus allowing the app to close naturally once the user clicks Back again). But I'm not seeing this method! What gives?
http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.windows.navigation.navigationservice.removebackentry(v=vs.105).aspx
yes your point is correct. you can clear the back entry and exit by the following piece of code.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
while (NavigationService.CanGoBack)
{
NavigationService.RemoveBackEntry();
}
}
you can use this to terminate the app in Windows Phone 8 (Just remember to save all your program data before calling this ;-))
App.Current.Terminate();
Related
I have a C# WinForms application running on .NET Framework 4.0.
When the user is inactive for a certain period of time, I want it to hide all the displayed forms and show an icon in the notification area. When the user clicks that icon, a login form appears and if the credentials are valid, it opens the exact forms that were open before.
To do this, I store the list of open forms in a List of Form objects and hide them, like this. This method is called by a Timer:
private void LogOut()
{
foreach (Form form in Application.OpenForms)
if (form.Visible)
{
GlobalVariables.formList.Add(form);
form.Hide();
}
}
When the credentials are validated, I try to make the forms visible again, like this:
//Show the previous forms.
foreach (Form form in GlobalVariables.formList)
form.Visible = true;
//Clear the forms list.
GlobalVariables.formList.Clear();
If I only have the MainForm open when I hide the forms, it shows it back fine when logging back in. If I have any other forms open (which are opened using ShowDialog() from the MainForm), the program will crash on form.Visible = true; and give me the following error message:
ObjectDisposedException was unhandled
Cannot access a disposed object
How can I fix this problem? An alternative way of doing what I'm trying to achieve would also be great.
Please note that using a try - catch block to determine if the form has been disposed and just relaunch the form is not an option as the user may have unsaved input in the hidden forms.
I couldn't manage to find anything related online in over 3 hours of search so any help would be much appreciated!
EDIT: After trying various things, I have noted that the problem only occurs on forms I have opened forms using ShowDialog(). If I only have forms opened using Show(), everything works fine.
However in my case, using Show() is not an option because I cannot have the user click on things in the parent form. Hiding the parent form is not an option either as he needs to see information in the parent form.
Clearly hiding a form is more impactful than you counted on. Your code was involved in a security review that Microsoft conducted on Winforms. Very thorough, not often visible in the way it behaves but very visible in the source code. One rule is imposes is that a user should never lose control over the application.
A dialog is very troublesome that way. The core problem is that ShowDialog() creates a modal window that disables all the other windows. That creates an opportunity for malware, very easy to take advantage of, all it has to do is hide a dialog and you snookered the user. There isn't any way that the user can gain control of the app again. The one window that was enabled is hidden with no way for the user to re-activate it again. All the other windows are disabled so trying to click on them, or their taskbar button, will not have any effect. All that's left is for the user to use Task Manager to kill the app. And if the user account is locked down then that's not an option either.
I can hear you sputter by now: "But, but, it is my code that hides the dialog, not malware!" That's not the way it works in Windows, there's no way to tell that it actually was your code that did it. Not only because it could be injected code, it doesn't even have to be code that runs in your process. Any code can do it, it is part of the winapi.
So there's a specific counter-measure against this built into Winforms, it will automatically close a form if it is hidden while operating in dialog mode. Which of course has a big impact, code that was written after the ShowDialog() call will now run. Anything is possible, but a sure-fire mishap in your case is that this disposes another window and an attempt to revive it will die.
The rough guidance here is that you are doing it wrong. You are trying to build a security system on top of one that's already highly secure and heavily tested. And it is very risky, handling passwords yourself is a very good way to make the overall system much less secure. The average user will of course favor picking the same password as he used to login to Windows. Makes it much easier for an attacker to harvest that password.
Call LockWorkStation() instead.
After many hours of trial and error, I found out what the problem was.
My understanding of modal forms was that code would continue executing in the parent form only after the modal form was closed. In fact, the specification found on MSDN states:
A modal form or dialog box must be closed or hidden before you can continue working with the rest of the application.
This introduced a subtle bug in the way I handled the forms. This is the code I used to display the forms:
using (var theForm = new CreateInvoice())
{
theForm.ShowDialog();
if (theForm.Updated)
{
GetInvoiceStatus();
}
}
The using statement disposes of theForm as soon as the statement exits. Normally, this works perfectly fine as it would be called only when the user closes theForm. However, because ShowDialog() permits the parent form to continue its work when it is hidden, this meant that the code actually exited the using statement, which effectively disposed of theForm, resulting in my error.
Testing, it seems that Hide()ing a modal dialog - closes it. It actually triggers the FormClosing event.
Tested like this: (Also, see this answer.)
private void button1_Click(object sender, EventArgs e)
{
Form1 f1 = new Form1();
f1.ShowDialog();
}
private void button2_Click(object sender, EventArgs e)
{
Hide();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
MessageBox.Show("Closing");
}
EDIT
I noticed this actually doesn't solve the mystery, just adds more information. Here's another piece of information: When you're setting Visible to true - you're not showing it modal again. This time it's equivalent to Show().
One suggestion to the design: instead of saving forms(views), you should save the data that the form holds(Model) and destroy the form. When you need the form again, create it back with the data(model). First, this can resolve this mysterious dispose problem, second, each form will need GDI resource, which are limited, if two many forms, you'll encounter the memory and GDI problems.
As how to do this, please refer the MVC or MVP design pattern.
BTW my guess on this problem: when you make the form visible, it will try find its parent, but its parent may be already disposed. I encountered this problem once, it throws the object disposed exception.
I have a C# .Net 3.5, winform (displaying graph) that needs to remain open as a front screen. I refresh the graph during the datagridview RowEnter event of the calling window. I open graph winform as show(), and use TopMost = true. Everything works fine till I open another application like Word; Graph window still remains in the front of Word.
Is there an application event gets triggered when another application opens on top of my application, when I can close the open graph screen. Or, please let me know if you have a suggestion about the different approach.
Look at Form.Deactivate Event. It is raised when the form loses focus and is no longer the active form. You can use this event to Close the form
Sorry but I can't get the sense of your question. You set TopMost=true and the next moment you want it to hide behind another application... ????
This solution method is 100% working, considering that the login form name is loginForm.
Simply create the following method:
private void hideLogin()
{
if (System.Windows.Forms.Application.OpenForms["loginForm"] != null)
{
System.Windows.Forms.Application.OpenForms["loginForm"].Hide();
}
}
Call this method through task:
Task HideLoginTask = new Task(hideLogin);
HideLoginTask.Start();
I'm writing a windows phone app, and I want to know how to alert and make sure the that user really wants to exit the app on the back key press. Pretty simple.
Thanks.
I assume your navigation is set up such that the user can only exit from the first page. If so, in that page, you can override the OnBackKeyPress event and cancel the button press. I haven't tested this code, but seems like it should work:
protected override void OnBackKeyPress(CancelEventArgs e)
{
if(MessageBox.Show("Are you sure you want to exit?","Exit?",
MessageBoxButton.OKCancel) != MessageBoxResult.OK)
{
e.Cancel = true;
}
}
Edit - I'll leave this here as an example of overriding the back button, but the correct answer in this context is to not implement the feature.
While the previous answer about cancelling OnBackKeyPress may technically work, it could cause your app to fail certification requirements. See the following link:
http://msdn.microsoft.com/en-us/library/hh184840(v=VS.92).aspx
5.2.4.2 – Back Button: First Screen
Pressing the Back button from the first screen of an application must close the application.
I would recommend not implementing this functionality.
Something is wrong with my program, while is using the application and when exit and resume, the application crashes..
I'm using a List variable but, when the application resume, it has nothing in it.
I was using this.
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
if (State.ContainsKey("c"))
{
App.Contenedor.Add((List<int>)State["c"]);
}
}
protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
State["c"] =(List<int>)App.Contenedor[0];
}
It seems working, but I'm not sure.. what do you think people?
You need to read up on Tombstoning, the process where application sleeps while not active.
Check out the Activated and Deactivated events.
You are saving/restoring data in the wrong methods. You shoud be saving data in OnNavigatedFrom and restoring data in OnNavigatedTo.
The Tombstoning is rarely invoked in Mango anymore - your application sort of exists in limbo while you are using other apps on the phone.
All the events that have to do with saving and restoring state are in App.xaml.cs - respond to them if necessary.
I have a C# windows forms application. The way I currently have it set up, when Form1_Load() runs it checks for recovered unsaved data and if it finds some it prompts the user if they want to open that data. When the program runs it works alright but the message box is shown right away and the main program form (Form1) does not show until after the user clicks yes or no. I would like the Form1 to pop up first and then the message box prompt.
Now to get around this problem before I have created a timer in my Form, started the timer in the Form1_Load() method, and then performed the check and user prompt in the first Timer Tick Event. This technique solves the problem but is seems like there might be a better way.
Do you guys have any better ideas?
Edit: I think I have also used a background worker to do something similar. It just seems kinda goofy to go through all the trouble of invoking the method to back to the form thread and all that crap just to have it delayed a couple milliseconds!
I would use Form1_Shown()
Use the Shown event. It seems to suit what you need, and will only display the first time the form is shown.
Form f1 = new Form();
f1.Shown += new EventHandler(f1_Shown);
public void f1_Shown(object sender, EventArgs e)
{
// Show dialog in here
}
Try the "Shown" event:
Form.Show Event
Using a Windows.Forms.Timer is a good, stable, well-known, and easily understood technique for doing what you want. I would avoid any other timer objects.
The form's Shown event works well.
Overload / override the Show method. (My preferred technique for greater control.) In this method, I would do the checking needed. When ready, I would call the base.Show method, then do any other processing, such as message boxes, prompts, logging, or whatever.