I have some session management code in a silverlight application. As part of that session management, I automatically log the user out if they are idle too long. When the user logs in again, any ChildWindow that was open in the previous session will still be open. All other session data is reset though, so the ChildWindow is effectively orphaned. Any attempt to work with it will throw errors. How can I kill any ChildWindows when I do the logout?
How can I find any child window that may exist, and kill it so the logout can work correctly? My first thought is to start looking along the lines of this.GetVisualDescendants().OfType<ChildWindow>(); from the shell. However, in testing, this was empty even when I had a childwindow open.
The app is a silvelight C# app using Prism & MEF.
Edit - adding more detail / another way to phrase the question:
So the program flow would be something like:
User Logs in to the silverlight Appliction.
User navigates around in the app and opens a ChildWindow.
User abandons their computer to refill coffee and ends up in a 20 minute conversation.
User's Silverlight "session" times out. All user-specific information is discarded and the login window (another ChildWindow) is shown.
User returns to computer and sees a login prompt, logs in.
User sees the ChildWindow they opened just before heading out for coffee.
User tries to click on something in the ChildWindow and gets an error, since all the context that the ChildWindow had was thrown away when their "session" ended.
I'd like to add to my session timeout code (or even post-login code), something that finds any open ChildWindow and closes it, in order to prevent this situation that leads to the error.
So, I apparently stumped everyone, or more likely didn't make my question interesting enough.
I did find a way to solve this though. I created a custom base class for all child windows in the application. In that base class, the ChildWindows register/unregister (in Loaded/Unloaded event handlers) themselves from a static list that can be used to get a reference to any active ChildWindows.
Related
Background
I'm creating a windows forms application that implements the MVP-VM pattern. This post explains the overall approach I'm taking:
http://aviadezra.blogspot.ca/2009/08/mvp-mvvm-winforms-data-binding.html
My application has a main window that opens on application start-up. The main contents of the application are hidden until the user logs in, after which the user controls which expose application functionality are revealed.
The main window has multiple presenters, each one representing a different set of logically grouped functionality. When the application starts, only the presenter that creates the login dialog is populated. Then, once the user logs in, the remaining presenters are created. I feel this is a good way to prevent users from somehow accessing functionality until they are logged in.
Question
When a user logs out, I'm having trouble deciding what needs to be done. I don't want to re-create the main window, but the state of the main window at login is I think what I'm trying to achieve (only the one presenter initialized). When someone logs out, should I dispose all presenters except for the one that creates the login screen? How do I do that? I don't imagine just setting the presenters in the main form to null would work, eh?
I have a WPF-application with multiple unrelated Windows, i.e. there is always one MainWindow and optionally many others with no owner.
If these windows get grouped in the taskbar, windows will provide the action "Close all Windows" in the taskbar context menu.
If it is clicked, each Window of my application gets an individual close-command in an order I cannot control.
Problem:
Some of my windows may ask before closing, if it's okay to cancel pending changes. This is annoying and confusing if there are many of those.
What I want is: If the MainWindow is asked for closing, I want to prompt once, if that's ok. If yes, all windows should close silently, otherwise stay open.
But my MainWindow is not the first one, to process the closing procedure.
I have already found out, that I probably need to check the Windows Message Loop of my MainWindow for some WM_SYSCOMMAND with wparam SC_CLOSE.
(see How can I distinguish between "Close All Windows" and "Close" individual windows in MFC with Windows 7?)
But how can I evaluate this, before I execute the closing-routine for any other window?
ComponentDispatcher.ThreadPreprocessMessage in my mainwindow comes too late, it fires after some other window has started the closing procedure.
This question is somehow related to this one:
Odd form closing behavior when using taskbar's Close All Windows
Personally, I would just leave things as they are. I can see how having several prompts to save/cancel changes could be annoying, but it doesn't seem confusing to me. And while annoying, it seems like a minor annoyance, and frankly one that might teach the user to not use the "Close all windows" option when they have left a bunch of these windows open. That said…
As the question you've found points out, there is no built-in way to distinguish the "Close all windows" from a regular "Close window" command. The system is simply sending the messages to the windows in sequence.
In MFC (i.e. the context of the other question), you can call AfxGetCurrentMessage() to retrieve information about what actually instigated the SC_CLOSE message. If it was user input that was translated to a close command, there will be some type of user input (keyboard, mouse, etc.) as the current message. Otherwise, you'll just see the WM_SYSCOMMAND itself.
But you can't apply the same approach in WPF, because WPF doesn't provide a GetCurrentMessage() method or its equivalent (as far as I know). The only access to window messages you get is to override the Control.WndProc() method, and by the time you get the close command, the most recent window message there will always be the SC_CLOSE.
It seems to me that the best you can do is use the WndProc() override to track incoming messages, so that you can reset a flag when non-close-command messages come in.
Then, when you get the close command and display the user prompt, you can check that flag. If it's set true, then you can ignore the prompt and just use whatever the user most recently selected. Since you're clearing the flag any time non-close-command messages come in, the first close command received will always display the prompt.
Another alternative would be pre-emptively close all the remaining windows. Here you'd still have the prompt have some kind of "apply to all other windows" option for the user, but instead of setting of just relying on the flag, you could actually close all the other windows explicitly.
Neither of these are ideal, from a user-interface perspective. The main problem is when the user tries to close just a single window. In the first approach, the user will see the "apply to all other windows" option in the prompt even though there won't be any other windows to close. The second approach is a bit more self-consistent, but adds a feature you may or may not want: the user can close all windows in the program any time they are closing just one window.
Neither of these behaviors are exactly standard Windows user interface behaviors. I.e. in trying to save the user some annoyance (and confusion, though like I said, I don't see that part being the case), you introduce what itself could be potentially confusing to the user.
Given that it involves additional work coding, and may simply exchange one annoying/confusing result for another, the best solution may be simply to not try to address the issue at all.
i have the following problem. When the user closes the Windows store app, i want a text file with data to be saved.
What method should i write so that when closing the app a file gets saved ?
This article describes the application lifecycle of a Windows Store App.
If you look at the very first figure, you can see that there are only 3 events related to application lifecycle:
Activated - Raised when program first starts
Suspended - Raised when program is suspended (i.e. the user returns to the Start Screen or another app)
Resuming - Raised when the program is awakened from its suspended state.
The fourth transition - the one to the "Not Running" state - has no such notification event. The reason is: you don't really know when the app will fully close. Nor should you - Microsoft wants you to perform all of your state-saving logic in the transition from "Running" to "Suspended." In this way, they can free up resources when they deem necessary.
Even if the user forces the program to terminate (by right-clicking it and selecting "Close" from the task menu), you will enter the "Suspended" state for exactly 10 seconds before the program is terminated. So you can rest easy that your state-saving logic will always be executed.
you don't really know when the app will fully close. Nor should you...
I don't agree with this - Microsoft are copying this from Apple, and I don't know why, I never liked Apple's implementation either.
If your user makes changes to your App, then closes it using the keyboard or gesture, then restarts it say after 6 seconds, all changes are lost.
I don't see any way as a developer to get around this. Whoever decided that closed events (and exit buttons for that matter) are evil is an idiot.
I am trying to code an app for work where our clients can edit certain fields. When they click edit, the code will lock the data to be editted. And when they click save the data will unlock. But I am having trouble deciding if I can unlock the data when they click elsewhere, go to another page or site, or even close the browser.
What's a good way to decide if the user has left the edit page?
(We are using C# .NET 3.5 and JQuery and a SQL Server 2005 DB).
If you really must use pessimistic locking you could add check in Session_End and unlock all locks that this user set in current session. Use onUserExit jQuery plugin to end session if user closes the browser window or goes on another site, here is the example :
https://stackoverflow.com/a/10481972/351383
You can make use of "onunload" event of html tag. This event is raised
- when Page is closed using X button
- when Page is redirected(In your case user clicks on edits and move on to different link without saving.)
Hope this helps!!
Your question is being understood as "what's a good way to decide if the user has abandoned the edit page without having clicked 'Save' to unlock the field?"
But I am having trouble deciding if I can unlock the data when they click elsewhere, go to another page or site, or even close the browser.
All the scenarios in which someone looks at another page from the same application might mean another window in the same session - perhaps to check something. You don't want that to trigger an unlock because your user could still have a window open in which they can submit the edit.
The other scenarios where the user leaves the page can use onUserExit.
However, you omit from this list the scenario "user goes to lunch leaving webpage open". This is why pessimistic locking is problematic.
Therefore, rephrase the problem as "the user has clicked Edit, but then failed to make the amendment and save within a reasonable time limit".
Basically, your lock should at some point expire.
Upon clicking 'Edit', the save lock kicks in and a timer (5 minutes?) starts, which is also visible on-screen. (If getting these in sync is an issue, make the client-side timer shorter than the server-side one). Your users must make the change and click Save within this time. You could perhaps add an Extend button to extend the time.
The principle is that you need to determine that someone has left it too long, not that someone has left it. You also show to users that having clicked Edit you are expecting them to make an edit some time soon.
You will need to code your system to unlock fields where the lock has expired.
This has the benefit that your countdown will look 'cool' to the sorts of people that request such edit locks.
My basic issue is this, I have events firing on pages I've left based on network activity that are causing problems when I thought the old forms were being destroyed.
More detailed information: I am writing a windows phone app that communicates with a network player. I have a static instance of my communication class in my App class so all the forms can share the connection, and all my forms subscribe to it and process results within that form. From a main menu you can choose one type of source and it opens a file browsing form that refreshes a listbox as you navigate, cancels the back button and refreshes the new contents to simulate file navigation until you are the root folder. The app doesn't know if you're clicking on a file or folder, it gets a network message when media starts playing and watch for that and then navigate to a "play" form. I had been using all .Navigate's for this until now and it worked great until I added another branch off the main menu for a new source. Although the new source is completely different, the device sends a lot of the same generic commands which just mean something else in the current context. After visiting the my file browser form and going to my new source, a play command from the network, which means something else now, would cause my to jump into my old "play" form from the previous source as if I was still on the file browser form, which isn't intended.
So I've tried many things and have it kind of working now but it's message and I lose some features. Currently I changed from using all .navigates, also in the back button override, to trying to use the stack and navigate.goback's. I pass variables when needed using globals in App and unhook my net listeners from the form, goback, and then connect them in the new form's listeners in it' navigatedto. I think there is timing issue though as in some cases I needed to send a command to the media box as it's changing and it ended up triggering the wrong event handler again. I think the easiest solution, if possible, and they way I though it would work is if each time I navigated from the form it old one, it's handlers, etc were all destroyed and I didn't have to use the stack at all, handling all the back buttons myself.
I know that's a long description and thanks if you made it this far, hopefully it made some kind of sense. Does anyone have any suggestions on what I can do?
As a side note I'm a long time self-taught VB programmer who has been stuck in .net 2.0/winforms and I've just now made the move to C#, OOPs, and XAML to write my first Windows Phone app so it's likely I'm doing something stupid or overlooking something obvious...
It is likely because something has retained reference to the form. The most common cause is event handlers.
So, if your static class exposes an event, and you subscribe to that event in a form, you must unsubscribe from the event when your form closes / navigates, otherwise the form will remain in memory....
If that isn't the case, look for something else that is acquiring a reference to your form and not releasing it.
Most likely the problem is based on a bad application architecture, when it comes to handling commands send from the UI.
When you say 'sends a lot of the same generic commands which just mean something else in the current context.' you most likely reveal the source of the problem.
As a workaround, you can define an interface, that your communication class implements. Each form has it's own method it calls on a communication class instance.
If you indeed receive a command from a phone page, that is no longer in view, just don't process it.
You can store the navigation history to always know what page is the only one allowed to send commands to a communication class.