Condividi tramite


Focus Overview

Microsoft Silverlight will reach end of support after October 2021. Learn more.

Focus is an input system concept that is relevant to controls in Silverlight. The control that is currently focused can receive the keyboard input events KeyUp and KeyDown and can thus use keyboard input. Focus is also relevant to the automation system and accessibility. Within a Silverlight-based application, the user can traverse controls in the UI by using a tab sequence. Traversing the tab sequence sets focus to the controls. You can influence the tab sequence as well as navigation behavior by setting several properties defined on the Control class.

Controls and Focus

Only an element that is a Control class can receive focus. Notable visual elements that are thus not focusable include:

In order for a control to receive focus, the following must be true:

  • IsEnabled is true.

  • Visibility is Visible.

  • Focus cannot be entirely outside the Silverlight content area (for example, cannot be in the browser host’s UI).

  • IsTabStop must be true. Most controls use true as the default value.

Controls that can receive and process keyboard input are the most obvious cases where obtaining focus is important. This is because only the focused element can raise the KeyUp and KeyDown events. But other controls might be designed to receive focus in order to use keyboard keys as activators or accelerators. For example, a Button supports an access mode whereby you can tab to the button in a tab sequence, then press the SPACE key in order to "click" the Button without moving the mouse.

GotFocus and LostFocus

GotFocus is raised whenever focus changes from one control to another control within the Silverlight content area, and also in the case where an application first starts and the first time a control receives focus. GotFocus is raised by the control that receives focus. LostFocus is raised by the control that was previously focused.

Both GotFocus and LostFocus are routed events that bubble; for more information about routed events, see Events Overview for Silverlight. The scenario for bubbling is for composition of controls. At the composition level, focus might be on an object that is a composite part of a larger control. The implementer of the composite control might want the control design to take actions that apply regardless of which component part is focused, or to take different actions if focus leaves the immediate composition and goes to a different control.

If you are consuming existing controls, you generally are most interested in the focus behaviors of the control and not its composite parts, which is the first point at which you as control consumer can attach event handlers without resorting to retemplating the control. But you also have the option of checking for bubbling GotFocus and LostFocus events on your containers for larger page composition: objects such as StackPanel or Grid, or also the root element UserControl. However, because of the bubbling behavior, it might be useful to check the OriginalSource value in each GotFocus and LostFocus event. You might do this to verify that the source of that focus event is relevant to something that should be done on the object where the handler is attached. That object might be one that is upwards in the object tree from the OriginalSource.

Also, if you are authoring a control, you might be interested in the event-related override methods OnGotFocus and OnLostFocus. These methods provide a way to implement the handling of the event as a class method rather than as an attached handler on instances.

The focus events have an asynchronous implementation, which is a necessary performance optimization in Silverlight. However, you can check focus synchronously in the body of a handler by calling FocusManager.GetFocusedElement.

The Focus Method

The Control base class provides a Focus method. Calling this method programmatically attempts to set focus to the control where the method is called. Focus has a Boolean return value that informs you whether the focus attempt is successful. Possible reasons for failure to set focus include each of the points mentioned in Controls and Focus previously in this topic. If you call Focus on the control that already has focus, no events are raised, but the method still returns true so that the method call is not interpreted as a failure to force focus to the intended target.

Tab Sequences

Controls that are rendered in a UI are placed in a default tab sequence. The TAB key has special handling on controls to enable this, such that the element that receives the TAB key input loses focus and the next control in the sequence gets focus, with the appropriate GotFocus and LostFocus events raised. SHIFT+TAB is similar to TAB, but traverses the tab sequence in the reverse direction.

If you call the Focus method, focus will potentially exit the current position in the tab sequence, and be positioned at a new point in the tab sequence. Other user-initiated actions that are based on mouse behavior or accelerators might also cause focus to change and a repositioning in the tab sequence. Note that such user actions are typically handled by individual controls or other UI regions, which handle another input event and then call Focus as part of their implementation.

In order to be in the tab sequence, the control must be focusable as per the requirements listed in Controls and Focus.

In addition to IsTabStop, controls have the TabIndex property and the TabNavigation property. These properties enable you to alter the default tab sequence and behavior. TabIndex declares the sequencing, and TabNavigation declares the behavior for any nested tab sequences within the control.

IsTabStop is true by default for most controls. Certain control classes, such as Label, initialize with IsTabStop false. If IsTabStop is false, you cannot programatically set focus to the control with Focus, users cannot focus it, and the control receives no keyboard input events. For a control such as Label, that behavior is all by intention, because you want the user to interact with the control that is labeled, not the label itself.

Layout containers or any collection that contains multiple controls have a default ordering of the tab sequence. The default tab sequence order is the order that the items appear in the collection. If the UI is defined in XAML, the order in the collection is the same order as they are defined in the XAML. For example, the following XAML declares a UI where the default tab sequence would first tab to Button1, and then to Button2. Neither of the Button elements declare an explicit TabIndex value.

<StackPanel>
  <Button Name="Button1">Button 1</Button>
  <Button Name="Button2">Button 2</Button>
</StackPanel>

To change the default tab order, you provide a TabIndex value for one or more elements in the UI. Within a container, the lowest value for TabIndex is the first item in the tab sequence. If no explicit TabIndex is specified, then the TabIndex is interpreted to be the maximum value when compared to any explicit TabIndex set value. For example, the following modification to the previous XAML changes the tab sequence so that Button2 is first in tab order, when compared to Button1 that does not have an explicit TabIndex value.

<StackPanel>
  <Button Name="Button1">Button 1</Button>
  <Button Name="Button2" TabIndex="1">Button 2</Button>
</StackPanel>

An element where IsTabStop is false is not in the tab sequence at all, and its value for TabIndex is irrelevant.

Tab Navigation

Certain containers are intended to change the tab sequence behavior when they are tabbed to. In particular, rather than tabbing into the container’s own children, the tab sequence should continue to the next peer element. This is the case for lists, and in particular for the ListBox control. A control enables this behavior by using a value of Once for the TabNavigation property.

Another possible value for TabNavigation is Cycle. This mode causes the tab sequence to remain inside the container where TabNavigation=Cycle is applied. You should use this mode with caution. The Cycle tab navigation container can create a “focus trap” for users who attempt to use tab navigation to traverse the entire UI, and this can be an issue for accessibility-related tools such as screen readers.

Tab Sequence and Browser Hosts

For a browser-hosted application, the tab sequence of Silverlight content is a nested sequence within the browser host's tab sequence. By default, users are able to tab out of the Silverlight content area and then focus other elements on the hosting HTML page, as well as bring focus to the UI controls of the hosting browser application (for example an address bar).

This behavior can be changed by setting TabNavigation to Cycle on the root UserControl. However, this practice should be used with caution, for the same accesibility reasons as listed in the previous section.

Visual Indication of Current Focus

As part of default behavior, most Silverlight controls provide a focus-specific style that visually indicates which control in a Silverlight UI has focus. In WPF without the visual state model, a separate property FocusVisualStyle provided this style. In Silverlight or when using the visual state model with WPF, you instead provide named states that make adjustments in control visual appearance. The states are changed whenever control overrides of OnGotFocus(RoutedEventArgs) or OnLostFocus(RoutedEventArgs) are invoked. Typically such states are named Focused or Unfocused, and the states sometimes apply to parts of a composite control rather than the full visual tree. For an example of how visual state models can handle focus states, see Walkthrough: Customizing the Appearance of a Button by Using a ControlTemplate.

Automation

Focus on controls has relevance to Silverlight accessibility and automation. For more information, see Silverlight Accessibility Overview.