WPF: LostFocus event for specific control / view / view model
I work in WPF using the MVVM pattern and it generally works pretty well as I wrap my brain around the nuances of both WPF and MVVM. However, I am currently stuck with a specific problem. My actual application is quite complex, so to keep things simple, drop Josh Smith's article with a close definition by pattern and use the application there.
Consider Figure 2 and imagine the user typed some things in the first and last name fields. The user is then completely removed from the stage (viewmodel), either by clicking on a different client tab, or perhaps a completely different viewmodel in the same application. In this case, I would like the application to ask "Hey, do you want to save your changes? Yes / No / Cancel" and respond accordingly. It showed ... problems.
Because I would like the user to be able to "undo" that the first pass implies the need for PreviewLostKeyboardFocus (since I could set Handled = true and undo the focus shift). However, several user actions (such as clicking on a tab in another workspace) do not change the keyboard focus. LostFocus covers me better in this regard, but only after the focus has already been lost (although of course I can turn it off?) And there are problems with determining whether the event was from the view itself (i.e. we go all view), or if it was just bubbling out of some contained object.
And the big picture about all of this is presumably a problem to the view, but then that implies writing the code in the view, not the magic view model. It makes me think that I am not looking at it right.
So I hope I'm missing some big conceptual a-ha that makes it all clear. Help?
source to share
You need to focus on your model, not your gaze. That is, what changes should your logic trigger? In this case, I would say this when an attempt was made to change the active tab.
So, you need a comprehensive view model whose responsibilities:
- Export a collection of all subspecies models (each appearing on its own tab)
- Track active (selected) sub-view model (i.e. active tab)
Your view will bind to these properties in the usual way:
<TabControl ItemsSource="{Binding Tabs}" SelectedItem="{Binding SelectedTab}"/>
The property will SelectedTab
apply your logic like this:
- Is the current tab dirty?
- If yes, ask the user through the service
- If the user cancels, do not change the active tab
- If the user saves or discards changes, change the active tab
I think the key thing you are missing is the overarching gaze model. Working through my ActiveAwareCommand example project might help you understand.
source to share