// Given a key, returns the appropriate navigation action. public static void TranslateKeyToKeyNavigationAction( FlowDirection flowDirection, VirtualKey key, out KeyNavigationAction pNavAction, out bool pIsValidKey) { pIsValidKey = true; pNavAction = KeyNavigationAction.Up; bool bInvertForRTL = (flowDirection == FlowDirection.RightToLeft); switch (key) { case VirtualKey.PageUp: pNavAction = KeyNavigationAction.Previous; break; case VirtualKey.PageDown: pNavAction = KeyNavigationAction.Next; break; case VirtualKey.Down: pNavAction = KeyNavigationAction.Down; break; case VirtualKey.Up: pNavAction = KeyNavigationAction.Up; break; case VirtualKey.Left: pNavAction = (bInvertForRTL ? KeyNavigationAction.Right : KeyNavigationAction.Left); break; case VirtualKey.Right: pNavAction = (bInvertForRTL ? KeyNavigationAction.Left : KeyNavigationAction.Right); break; case VirtualKey.Home: pNavAction = KeyNavigationAction.First; break; case VirtualKey.End: pNavAction = KeyNavigationAction.Last; break; default: pIsValidKey = false; break; } }
// Based on current element's index/type and action, return the next element index/type. public void GetTargetIndexFromNavigationAction( ElementType elementType, int elementIndex, KeyNavigationAction action, Rect windowConstraint, out ElementType pTargetElementType, out int pTargetElementIndex) { int totalItems; int totalGroups; totalItems = GetLayoutDataInfoProviderNoRef.GetTotalItemCount(); totalGroups = GetLayoutDataInfoProviderNoRef.GetTotalGroupCount(); global::System.Diagnostics.Debug.Assert(0 <= elementIndex && elementIndex < totalItems); global::System.Diagnostics.Debug.Assert(elementType == ElementType.ItemContainer); pTargetElementType = ElementType.ItemContainer; if (action != KeyNavigationAction.Left && action != KeyNavigationAction.Right && action != KeyNavigationAction.Up && action != KeyNavigationAction.Down) { throw new ArgumentException(nameof(action)); } int step = (action == KeyNavigationAction.Left || action == KeyNavigationAction.Up) ? -1 : 1; pTargetElementIndex = elementIndex; // Easy case: the action is along layout orientation, therefore handle it. if ((VirtualizationDirection == Orientation.Vertical && (action == KeyNavigationAction.Left || action == KeyNavigationAction.Right)) || (VirtualizationDirection == Orientation.Horizontal && (action == KeyNavigationAction.Up || action == KeyNavigationAction.Down))) { pTargetElementIndex = Math.Min(Math.Max(elementIndex + step, 0), totalItems - 1); } // The action is not in layout direction. We must jump to the next item in the same row/column. // We are not grouping, easy. else { // TODO: verify startAt int maxLineLength = DetermineMaxStackingLine(); int nextIndex = elementIndex + step * maxLineLength; if (0 <= nextIndex && nextIndex < totalItems) { pTargetElementIndex = nextIndex; } } global::System.Diagnostics.Debug.Assert(0 <= pTargetElementIndex && pTargetElementIndex < totalItems); return; }