Microsoft Silverlight, versions 3 and greater
Silverlight managed programming model and Silverlight XAML
This technique relates to:
See User Agents Supported for general information on user agent support.
The objective of this technique is to introduce key handling that exists at the application root level of a Silverlight application, rather than per-element key handling. Event handling at the application level as opposed to at the element level is one way to address key equivalence. The key events provide key equivalence for particular user interface elements that a user might otherwise interact with using a mouse. This technique is related to events in the Silverlight programming model, as opposed to in the HTML DOM.
Handling key events at the root level of an application rather than only on the element that was the "source" of a key event is possible because of a Silverlight programming model feature known as event routing. For more information on event routing and how it works, see Events Overview for Silverlight.
This technique demonstrates a "menu" approach to key handling and user interaction. This technique is presented as a companion to SL9: Handling Key Events to Enable Keyboard Functionality in Silverlight, which can be thought of as an "accelerator key/hotkey" approach. The "menu" approach towards keyboard equivalence is perhaps just as common as the "hotkey" approach. It is often simpler to document a menu's key equivalence in a user interface than it is to document key equivalents of particular regions of an application, or to communicate to users that where the current focus is placed is relevant to how keyboard keys are interpreted by the application, even if the key action is relevant to only one of the controls in an interface. If all keys are handled at the top level, the specific focused element is no longer relevant.
In order to originate a key event that Silverlight application code
can detect, some element in the Silverlight application must have keyboard
focus. One way to assure keyboard focus is to focus the Silverlight
plug-in as a whole, as called from within an event handler for Application.Startup
.
This is shown in the examples.
If an application does handle keys at top level, care should be taken
to not interfere with specific text entry control behavior, such as
typing into a TextBox
. To avoid interactions, the
design of key equivalence at the top level of an application typically
relies on combinations with key modifiers. The Control/CTRL key is
a key that is often used for this purpose. Application authors should
also be aware of the implications of browser hosts that might handle
the key event at HTML DOM level without making that event available
to the Silverlight programming surface. For more information on this
concept, see "Keyboard Events and Browser Hosts" section
of Keyboard
Support Overview for Silverlight on MSDN.
Application authors are responsible for correctly documenting the
accelerator keys that are pertinent for their application. There are
a variety of techniques for documenting user interface actions that
are not described here. One possible suggestion is to include a generalized "Help" button
that appears early in the application's reading order, which is focusable
and has an AutomationProperties.Name
value available as the text content
or equivalent. Such a button can be activated without knowing any of
the application's accelerator keys, and the activation result could
be a new text element that enumerates the possible keys. For example,
the application could display a Silverlight Popup
with
the following content:
This example has only one interactive control for simplicity, but
with two possible key combinations for that control being handled as
actions. The purpose and explanation of the control is reported through
a TextBlock
that is associated with the labeled control
through use of AutomationProperties.LabeledBy in
XAML. The control being illustrated is MultiScaleImage
,
which supports a zoom-in metaphor for examining an image that redraws
at increasingly fine resolutions. For more information on MultiScaleImage
,
see Deep
Zoom on MSDN.
The following is the startup logic at application level that sends focus to Silverlight in the HTML DOM.
private void Application_Startup(object sender, StartupEventArgs e)
{
this.RootVisual = new MainPage();
//bring overall DOM focus to Silverlight area, so that keys are captured by Silverlight
System.Windows.Browser.HtmlPage.Plugin.Focus();
}
The following is XAML UI for the main page.
<UserControl xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
x:Class="ApplicationLevelKeyHandling.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400" KeyUp="UserControl_KeyUp">
<StackPanel x:Name="LayoutRoot" Background="White">
<Button Name="bInstructions" Click="bInstructions_Click">Get Help</Button>
<Popup Name="p">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock FontWeight="Bold">Key</TextBlock>
<TextBlock FontWeight="Bold" Grid.Column="1">Action</TextBlock>
<TextBlock Grid.Row="1">Ctrl + Alt + Plus</TextBlock>
<TextBlock Grid.Row="1" Grid.Column="1">Zooms in on the image</TextBlock>
<TextBlock Grid.Row="2">Ctrl + Alt + Minus</TextBlock>
<TextBlock Grid.Row="2" Grid.Column="1">Zooms out of the image</TextBlock>
<Button Grid.Row="3" Click="button1_Click">Close this Help</Button>
</Grid>
</Popup>
<MultiScaleImage x:Name="deepZoomObject"
Source="source/dzc_output.xml"
MouseLeftButtonDown="DeepZoomObject_MouseLeftButtonDown"
MouseRightButtonDown="DeepZoomObject_MouseRightButtonDown"
AutomationProperties.LabeledBy="{Binding ElementName=lblInstructions}"/>
</StackPanel>
</UserControl>
The following is the C# logic. Note how the key handlers and mouse handlers reference the same logic function.
private void UserControl_KeyUp(object sender, KeyEventArgs e)
{
if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control &&
(Keyboard.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt &&
e.Key == Key.Add)
{
DZIn();
}
if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control &&
(Keyboard.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt &&
e.Key == Key.Subtract)
{
DZOut();
}
}
private void DeepZoomObject_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
DZIn();
}
private void DeepZoomObject_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
DZOut();
}
private void DZIn()
{
this.deepZoomObject.ZoomAboutLogicalPoint(3, .5, .5);
}
private void DZOut()
{
this.deepZoomObject.ZoomAboutLogicalPoint(.333, .5, .5);
}
private void bInstructions_Click(object sender, RoutedEventArgs e)
{
// Set where the popup will show up on the screen.
p.VerticalOffset = 25;
p.HorizontalOffset = 25;
// Open the popup.
p.IsOpen = true;
}
void button1_Click(object sender, RoutedEventArgs e)
{
// Close the popup.
p.IsOpen = false;
}
This example is shown in operation in the working example of Application Level Key Handling.
Resources are for information purposes only, no endorsement implied.
Using a browser that supports Silverlight, open an HTML page that references a Silverlight application through an object tag.
Verify that keyboard focus is somewhere within the Silverlight content area, and not elsewhere in the hosting HTML or hosting browser user interface. If necessary, use TAB key to traverse the overall HTML tab sequence until an interface element within Silverlight displays a visual focus indicator.
Verify that the keys to be used as keyboard equivalent action triggers for the application as a whole are documented for users. For example, text or long text alternative documents key / key combinations and short descriptions of actions.
Verify that pressing the application-specific keys results in the action as expected in the application.
Move keyboard focus throughout other areas of the Silverlight application, and verify that the same keys continue to function application-wide.
#3, #4 and #5 are true.
If this is a sufficient technique for a success criterion, failing this test procedure does not necessarily mean that the success criterion has not been satisfied in some other way, only that this technique has not been successfully implemented and can not be used to claim conformance.