/// <summary> /// Invoked when an unhandled Mouse.MouseMove attached event reaches an element in its route that is derived from this class. /// </summary> /// <param name="e">The MouseEventArgs that contains the event data.</param> protected override void OnMouseMove(MouseEventArgs e) { // Validate the parameters. if (e == null) { throw new ArgumentNullException("e"); } // This will highlight (and bring comletely into view) the element underneath the mouse. There is a verion of this in the WPF ComboBox that waits for a // MouseEnter event from the element and then tries to figure out if mouse movement caused the event. This is cumbersome because a MouseEnter event can // be caused by the mouse being moved over the element, or the element being scrolled underneath the mouse. An element being scrolled underneath a // mouse that hasn't moved can cause a false highlighting of the element, so a whole 'nuther set of logic was required to see if the mouse had actually // moved. Since this event assumes that the mouse has moved, it is simpler just to find out what element is under the mouse and change the highlight if // it wasn't the last thing highlighted. DependencyObject dependencyObject = this.InputHitTest(e.GetPosition(this)) as DependencyObject; HighlightElement highlightElement = VisualTreeExtensions.FindAncestor <HighlightElement>(dependencyObject); if (highlightElement != this.HighlightedElement) { highlightElement.BringIntoView(); this.HighlightedElement = highlightElement; } // Because an intermediate class in the inheritance might implement this method, we recommend that you call the base implementation in your // implementation. base.OnMouseMove(e); }
/// <summary> /// Moves the highlight by a line in the direction specified. /// </summary> /// <param name="focusNavigationDirection">The direction in which to move the highlight.</param> internal void MoveByLine(FocusNavigationDirection focusNavigationDirection) { // The highlight selector never gets the focus. Instead, it simulates the focus property with a 'highlighted' property that provides visual feedback to // the user of the item that would be selected if they hit the mouse button or enter key. This allows the edit control to get all the keystrokes with // the exception of the few that generate commands for the highlight selector. One of those commands is to move the selection and highlight by a single // line. This will use the 'PredictFocus' to find the next element in the direction of navigation. The next item will get the highlight instead of the // focus in this paradigm. UIElement navigationStart = this.HighlightedElement == null ? (UIElement)this : (UIElement)this.HighlightedElement; HighlightElement nextElement = navigationStart.PredictFocus(focusNavigationDirection) as HighlightElement; if (nextElement == null) { // Clearing the selection when wrapping is enabled will trigger that informs the listener that the selection has been cleared. The listening // object can elect what to do. For example, the listener could choose to move the navigation to the start of the window or clear out some other // control that is linked to this selection. When wrapping is not enabled, the selection will reach the end of the container and just stay there // no matter how many times the navigation arrows are pressed. if (this.SelectionWrapping == SelectionWrapping.Wrap) { this.HighlightedElement = null; this.OnSelectionWrapped(new RoutedEventArgs(HighlightSelector.SelectionWrappedEvent, this)); } } else { // This will bring the element into view, highlight it and select it. The selection will trigger an event that the owner window can watch for to // take some action, like fill in another control with the selected item. It is the selection and not the highlight that determine which object is // chosen by the user. So even though visually an item has a highlight, when they choose an action it is the selected item that provides a value // from this control. nextElement.BringIntoView(); this.HighlightedElement = nextElement; this.SelectedElement = nextElement; } }