Saving and Setting Focused Element On UserControl Reload
I have two screens, one of which serves as a "pop-up" temporarily taking focus away from the first screen. When the first screen is reloaded I want to set focus to whatever element was last focused before the pop-up screen came up. Is there a way to save which UIElement is focused and then to set focus to that UIElement directly?
Here is the code behind for the screen which is setting focus. It stores the focused UIElement in a field on the model and tries to reset focus when the screen is reloaded. This doesn't actually set focus to that element and instead drops focus to another spot in the UI hierarchy.
The view is a scroll viewer which holds an itemscontrol with multiple buttons. Clicking these buttons brings up the second screen and I am trying to return focus back to the exact button that was pressed when the first screen is reloaded.
Here is the code behind for the screen which is setting focus. It stores the focused UIElement in a field on the model and tries to reset focus when the screen is reloaded. This doesn't actually set focus to that element and instead drops focus to another spot in the UI hierarchy.
The view is a scroll viewer which holds an itemscontrol with multiple buttons. Clicking these buttons brings up the second screen and I am trying to return focus back to the exact button that was pressed when the first screen is reloaded.
Code: Select all
public partial class ScreenView : UserControl
{
public ScreenView()
{
InitializeComponent();
DataContext = DataModel.CreateOrGet<Model>();
#if NOESIS
var weak = new WeakReference<ScreenView>(this);
Loaded += (s, e) => // weak
{
if (weak.TryGetTarget(out var target))
{
var model= (Model)target.DataContext;
//FocusManager.SetFocusedElement(target, model.FocusedElement);
//controlsSettingsModel.FocusedElement.Focus();
Keyboard.Focus(model.FocusedElement);
}
};
PreviewGotKeyboardFocus += (s, e) => // weak
{
if (weak.TryGetTarget(out var target))
{
var model = (Model)target.DataContext;
model.FocusedElement = Keyboard.FocusedElement;
}
};
#endif
}
#if NOESIS
private void InitializeComponent()
{
NoesisUnity.LoadComponent(this);
}
#endif
}
-
sfernandez
Site Admin
- Posts: 3183
- Joined:
Re: Saving and Setting Focused Element On UserControl Reload
The FocusManager allows you to create Focus Scopes which can store individual logical focus in different sections of the UI. For example, you can have a focus scope in your main screen and another one in your popup screen, so when the popup is closed you can set the focus to the main screen who will automatically set it to the previously focused element.
Could you please try that?
Code: Select all
FocusManager.IsFocusScope="True"
Re: Saving and Setting Focused Element On UserControl Reload
I was able to resolve the original issue that I was having. There were actually a few other things going on that were causing focus to behave incorrectly. The main thing was that the items of the itemscontrol were being updated and this would cause the itemscontrol to update and (I think) regenerate the UIElement for each row. This would cause the focus to be lost because whichever row of the itemscontrol was focused before, gets regenerated.
1. Is there an event for the itemscontrol that allows us to respond to when the UIElements have finished being repopulated? This would happen if an element is added, removed, or replaced in the itemsource.
Reading a bit more about FocusManager.IsFocusScope="True" this looks like the ideal approach. It didn't work in this particular case because of the issue above but this does seem like the ideal approach for other screens. For this case however, when we return to the original screen from the pop-up the "Loaded" event happens and sets the initial focus for the screen ("Loaded" happens when the screen is first opened and when returning from a pop-up). I haven't tested this but it seems like this would conflict with the focus changes performed by the FocusManager.
2. Is there a way to only use the FocusManager focus scope conditionally? Maybe this should be handled in a different way entirely.
1. Is there an event for the itemscontrol that allows us to respond to when the UIElements have finished being repopulated? This would happen if an element is added, removed, or replaced in the itemsource.
Reading a bit more about FocusManager.IsFocusScope="True" this looks like the ideal approach. It didn't work in this particular case because of the issue above but this does seem like the ideal approach for other screens. For this case however, when we return to the original screen from the pop-up the "Loaded" event happens and sets the initial focus for the screen ("Loaded" happens when the screen is first opened and when returning from a pop-up). I haven't tested this but it seems like this would conflict with the focus changes performed by the FocusManager.
2. Is there a way to only use the FocusManager focus scope conditionally? Maybe this should be handled in a different way entirely.
-
sfernandez
Site Admin
- Posts: 3183
- Joined:
Re: Saving and Setting Focused Element On UserControl Reload
Do you mean to listen from the XAML to an EventTrigger or similar? No, ItemsControl does not offer such kind of event, but when new items are added to the UI tree they launch the Loaded event, I don't know if in this scenario that could be useful.1. Is there an event for the itemscontrol that allows us to respond to when the UIElements have finished being repopulated?
As I mentioned before, the Loaded event is raised when an element is added to the tree. So if you remove it and add it back, it will launch the Loaded event again."Loaded" happens when the screen is first opened and when returning from a pop-up
The FocusManager just updates the FocusedElement in the focus scope. And only changes keyboard focus if the focus scope receives the focus, moving it to the previously FocusedElement.I haven't tested this but it seems like this would conflict with the focus changes performed by the FocusManager.
2. Is there a way to only use the FocusManager focus scope conditionally? Maybe this should be handled in a different way entirely.
Re: Saving and Setting Focused Element On UserControl Reload
I was able to find a work around for the original issue but I am still struggling to get FocusManager.IsFocusScope to work as expected. I started a separate thread which directly addresses this viewtopic.php?p=18000#p18000