aivanov
Topic Author
Posts: 15
Joined: 30 Sep 2024, 17:25

Saving and Setting Focused Element On UserControl Reload

26 Nov 2024, 19:32

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.
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
    }
 
User avatar
sfernandez
Site Admin
Posts: 3183
Joined: 22 Dec 2011, 19:20

Re: Saving and Setting Focused Element On UserControl Reload

28 Nov 2024, 10:23

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.
FocusManager.IsFocusScope="True"
Could you please try that?
 
aivanov
Topic Author
Posts: 15
Joined: 30 Sep 2024, 17:25

Re: Saving and Setting Focused Element On UserControl Reload

05 Dec 2024, 19:38

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.
 
User avatar
sfernandez
Site Admin
Posts: 3183
Joined: 22 Dec 2011, 19:20

Re: Saving and Setting Focused Element On UserControl Reload

10 Dec 2024, 15:34

1. Is there an event for the itemscontrol that allows us to respond to when the UIElements have finished being repopulated?
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.
"Loaded" happens when the screen is first opened and when returning from a pop-up
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.
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.
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.
 
aivanov
Topic Author
Posts: 15
Joined: 30 Sep 2024, 17:25

Re: Saving and Setting Focused Element On UserControl Reload

13 Jan 2025, 17:09

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

Who is online

Users browsing this forum: BrandonReinhart, MarioBarbero, Semrush [Bot] and 7 guests