1

SetFocusIndex is called when navigating away from a view. This should register/attach a DependencyProperty to the specified control.

GetFocusIndex is called upon returning to the view. This should extract the registered/attached DependencyProperty which holds the index of the last control (EightTileGrid item etc) that had focus.

I see the correct DependencyProperty being set , but when I retrieve it on back navigation it returns -1 value as if the property was never set.


Setting logic:

public static readonly DependencyProperty FocusIndexProperty =
DependencyProperty.RegisterAttached(
   "FocusIndex",
   typeof(int),
   typeof(GamePadFocusManager),
   new PropertyMetadata(-1));

public static int GetFocusIndex(DependencyObject obj)
{
    return (int)obj.GetValue(FocusIndexProperty); 
}

public static void SetFocusIndex(DependencyObject obj, int value) 
{  
    obj.SetValue(FocusIndexProperty, value); 
}

private void OnNavigatingMessage(NavigatingMessage navigatingMessage)
{           
  Messenger.Default.Unregister<NavigatingMessage>(this, OnNavigatingMessage);
  SaveFocusIndex();
}

 private void SaveFocusIndex()
 {
    var controls = VisualTreeQueryHelper.FindChildrenOfType<Control>(this).ToList();

    for (int i = 0; i < controls.Count; i++)
    {
        if (controls[i].ContainsFocus())
        {
           GamePadFocusManager.SetFocusIndex(this, i);
           break;
        }
    }
 }

Retrieving logic:

private void BaseTileGrid_GotFocus(object sender, RoutedEventArgs e)
{
    if ((FocusManager.GetFocusedElement() == this) || !this.ContainsFocus())
     {     

        SetFocusOnChildControl();
     }
}

public virtual void SetFocusOnChildControl()
{
    var focusIndex = Math.Max(0, GamePadFocusManager.GetFocusIndex(this)); 
    var contentControls = VisualTreeQueryHelper.FindChildrenOfType<ContentControl>(this).ToList();

    DispatcherHelper.BeginInvokeAtEndOfUiQueue(() =>
      {
        if (contentControls.Count > focusIndex)
        {
            if (this.ContainsFocus())
            { 
                GamePadFocusManager.FocusOn(contentControls[focusIndex]);
            }
        }
    });
}

Grid

public class BaseTileGrid : Control
{
...
}

Xaml:

  <GridLayout:BaseTileGrid  x:Name="recentlyWatched"
        Style="{StaticResource FourByTwoGrid}"
        ItemsSource="{Binding ItemViewModels}" 
        ItemTemplate="{StaticResource GridLayoutDataTemplateSelector}" 
        OverflowPageTitle="{Binding OverflowPageTitle}"
        MoreButtonCommand="{Binding MoreButtonCommand}"/>
Fabii
  • 3,820
  • 14
  • 51
  • 92
  • Can you explain in more detail, what happens at "back navigation"? Also, the context of usage would be interesting - is it WPF? (if so:) is your container a `DataTemplate` with viewmodel or a `UserControl`? (...) – grek40 Feb 25 '16 at 20:32
  • @grek40 On navigation back to the previous view BaseTileGrid_GotFocus is triggered which in turns calls SetFocusOnChildControl, here I check for the DependencyProperty FocusIndex that was set when the user previously navigated away from the page. If an index greater than (-1) is found then focus is given to the item of that index in the grid. My grid BaseTileGrid is a simple 4x2 grid which extends System.Windows.Controls.Control. The app uses a mvvm pattern. ItemViewModels is populated asynchronously and bound to ItemsSource. – Fabii Feb 25 '16 at 21:39
  • 1
    In a typical MVVM pattern, the view XAML would just be a presentation layer for you viewmodel. This implies, that you would need to store any extra information in the viewmodel and not in attached properties of the view. When your viewmodel is replaced, the view may be disposed of and when you reload it, a new view is created from the appropriate template. It will not necessarily be the same that you attached your property to. However, it all depends on the instantiation details of your view, I cant really see it from the information that you provided. – grek40 Feb 25 '16 at 22:15
  • @grek40 RE: When your viewmodel is replaced, the view may be disposed of and when you reload it" << Y eah that's what I think might be happening here. I'll do a bit more digging . The app is based of the default Xbox reference application so there are still some intricacies I need to look into. – Fabii Feb 25 '16 at 22:22

0 Answers0