Поделиться через


Mouse Support

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

Silverlight provides a set of events that enable you to respond to mouse actions, such as moving the mouse pointer or clicking the mouse buttons. Silverlight can also promote stylus input and multitouch input to an equivalent mouse action.

This topic contains the following sections.

  • Mouse Events
  • Mouse Event Handlers
  • Attaching a Mouse Event Handler
  • Defining a Mouse Event Handler
  • Some Mouse Events are Routed Events
  • Mouse Capture
  • The Mouse as a Stylus
  • Multitouch Events Promoted to Mouse Events
  • Right-click Mouse Button Events
  • Double-Click
  • Mouse Events Outside the Visual Tree
  • Drag-Drop
  • Mouse Events, Browser Hosts, and Operating Systems
  • Related Topics

Mouse Events

Silverlight provides the following set of mouse events.

Event

Description

LostMouseCapture

Occurs when the UI element loses mouse capture.

MouseMove

Occurs when the coordinate position of the mouse (or stylus) pointer changes.

MouseEnter

Occurs when the mouse (or stylus) enters the bounding area of an object.

MouseLeave

Occurs when the mouse (or stylus) leaves the bounding area of an object.

MouseLeftButtonDown

Occurs when the left mouse button is down or when the tip of the stylus touches the screen.

MouseLeftButtonUp

Occurs when the left mouse button is up or when the tip of the stylus leaves the screen, typically following a MouseLeftButtonDown event.

MouseRightButtonDown

Occurs when the right mouse button is pressed.

MouseRightButtonUp

Occurs when the right mouse button is released.

Mouse Event Handlers

As with general Silverlight and CLR event handlers, a mouse event handler implements a delegate that provides two categories of information. You can determine the sender of the event. The sender reports the object where the event handler is attached. You also receive event data. For mouse events or stylus events promoted as mouse events, that data is an instance of one of the following classes:

Matching the event data pair is a pair of delegates used for mouse events. MouseButtonEventHandler is used for the following events:

MouseEventHandler is used for the following events:

MouseWheel uses MouseWheelEventHandler. For more information on the MouseWheel event, see Mouse Wheel Input.

Attaching a Mouse Event Handler

You can attach mouse event-handler functions for any Silverlight object that includes the event as a member (any UIElement derived class). The following XAML example shows how to attach handlers for the MouseEnter and MouseLeave events for two Ellipse objects. Notice that in this case the two objects share the event handler for each event.

<Canvas>
  <Ellipse
    MouseEnter="Ellipse_MouseEnter"
    MouseLeave="Ellipse_MouseLeave"
    Height="100" Width="100"
    Fill="Blue" />
  <Ellipse
    MouseEnter="Ellipse_MouseEnter"
    MouseLeave="Ellipse_MouseLeave"
    Canvas.Left="120"
    Height="100" Width="100"
    Fill="Blue" />
</Canvas>

Attaching a mouse event handler using code is not covered here, and the technique for attaching event handlers in code is generally the same for any Silverlight event, mouse event or otherwise. For an example, see Events Overview for Silverlight.

Defining a Mouse Event Handler

The following example shows the corresponding Silverlight event-handler functions for the MouseEnter and MouseLeave events.

void Ellipse_MouseEnter(object sender, MouseEventArgs e)
{
    Ellipse ell = sender as Ellipse;
    ell.Fill = new SolidColorBrush(Colors.Red);
}
void Ellipse_MouseLeave(object sender, MouseEventArgs e)
{
    Ellipse ell = sender as Ellipse;
    ell.Fill = new SolidColorBrush(Colors.Blue);
}
Private Sub Ellipse_MouseEnter(ByVal sender As Object, ByVal e As MouseEventArgs)
    Dim ell As Ellipse = sender
    ell.Fill = New SolidColorBrush(Colors.Red)
End Sub
Private Sub Ellipse_MouseLeave(ByVal sender As Object, ByVal e As MouseEventArgs)
    Dim ell As Ellipse = sender
    ell.Fill = New SolidColorBrush(Colors.Blue)
End Sub

Using MouseEventArgs or MouseButtonEventArgs

All mouse events except MouseWheel use either MouseButtonEventArgs or MouseEventArgs for event data. MouseEventArgs has the following members:

MouseButtonEventArgs extends MouseEventArgs and adds the following members:

GetPosition is called to determine the X and Y coordinates of the mouse at the time that the event occurred. GetPosition returns a Point, which reports the X and Y values.

GetPosition is a synchronous method; you do not have to worry whether the mouse has moved in the time between the event occurring and the handler executing. GetPosition is a method rather than a property so that you can determine the X and Y coordinates in relation to coordinate systems of another object. Typically, you pass one of the following:

  • null: this evaluates coordinates in the overall coordinate space of the Silverlight content area. In this coordinate space, the point 0,0 is the upper left corner of the content area. relativeTo is a required parameter of GetPosition, so you must explicitly pass this null.

  • The sender value: this evaluates based on internal coordinates of the object where the event is handled. For example, you could compare the coordinate value from GetPosition relative to sender with the overall Width and Height of sender.

  • Some container object that you know is the immediate parent of sender and controls its layout, such as a panel.

The following illustration shows how the green Rectangle object uses the red Rectangle object as the value of relativeTo, in order to return mouse position values that are relative to the coordinate space of relativeTo. This means that clicking near the upper-left corner of the green Rectangle generates mouse position values that are negative with respect to the red Rectangle.

Returning relative mouse position values

Get position of upper left-hand corner.

The following example shows how to retrieve the current mouse pointer position for the object using a relative offset to another object referenceObject in the tree.

void Rectangle_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    // Return a Point object representing the x- and y-coordinates of the current mouse position
    // relative to the reference object.
    Point pt = e.GetPosition(referenceObject);
    // Display the current mouse position on 'Status', an existing textblock.
    Status.Text = pt.X + " : " + pt.Y;
}
Private Sub Rectangle_MouseLeftButtonDown(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
    ' Return a Point object representing the x- and y-coordinates of the current mouse position
    ' relative to the reference object.
    Dim pt As Point = e.GetPosition(referenceObject)
    ' Display the current mouse position on statusText, an existing textblock.
    statusText.Text = pt.X & " : " & pt.Y
End Sub
NoteNote:

Although MouseLeave uses MouseEventArgs, a meaningful mouse position is not available through GetPosition for the MouseLeave event.

Mouse Position, Screen Position, and Browser Zoom

Silverlight supports user-initiated browser zoom for certain browser hosts. Silverlight also supports browser auto-zoom features that are tied to operating system DPI, so long as your application configures it; for details, see EnableAutoZoom (Silverlight Plug-in Object). For a browser client host operating with browser zoom active, the screen position reported by mouse events no longer aligns with the original coordinate space in Silverlight. For these cases, you should call TransformToVisual against the coordinate space you are attempting to evaluate.

Some Mouse Events are Routed Events

Silverlight supports the concept of a routed event for certain events, such as some of the mouse events. Routed events in Silverlight all use the bubbling routing strategy. The bubbling routing strategy means that an event originates from a child object and is then routed up to successive parent objects in the object tree, presenting further opportunities to handle the same event and interact with the same event data as part of your control or application logic.

The following mouse events are routed events; they bubble up to parent objects in the object tree:

The following mouse events do not bubble; they only can be handled on the object that raises them:

Consider the following XAML example, in which MouseLeftButtonDown events are defined for a Canvas and two Rectangle objects. In this case, if you click the mouse over either Rectangle object, it receives the MouseLeftButtonDown event. The event is then bubbled up to the parent Canvas.

<Canvas
  Width="640" Height="480"
  Background="OldLace" Name="ParentCanvas"
  MouseLeftButtonDown="BubbleUpClick"
>
  <Rectangle
    Name="RectA"
    Width="100" Height="100" Fill="PowderBlue" />
  <Rectangle
    Name="RectB"
    Width="100" Height="100" Fill="Gold"
    Canvas.Top="50" Canvas.Left="50" Opacity="0.5" />
  <TextBlock Name="statusTextBlock" Canvas.Top="180" />
</Canvas>

The following example shows how to implement the MouseLeftButtonDown event handler for the corresponding XAML content in the previous example.

void BubbleUpClick(object sender, MouseEventArgs e)
{
  String msg = "x:y = " + e.GetPosition(null).ToString();
  msg += " from " + (e.OriginalSource as FrameworkElement).Name;
  statusTextBlock.Text = msg;
}
Private Sub BubbleUpClick(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
    Dim fe As FrameworkElement = e.OriginalSource
    Dim msg As String = "x:y = " & e.GetPosition(Nothing).ToString()
    msg = msg & " from " & fe.Name
    statusTextBlock.Text = msg
End Sub

Notice the use of the OriginalSource property in the handler. Here, OriginalSource reported the object that raised the event. This might be one of the rectangles, or it might also be the clickable area of the Canvas surrounding the rectangles. OriginalSource is how you can distinguish the actual event source object if you are handling the event on a parent object. Knowing the OriginalSource and using that value rather than sender in a handler is often useful if you are letting the event bubble up deliberately to a common parent of multiple possible event sources.

Commanding

In Silverlight 5, a small number of UI elements support commanding. Commanding uses input-related routed events in its underlying implementation, and enables processing of related UI input (a certain mouse action, a specific accelerator key) by invoking a single command handler. If commanding is available for a UI element, consider using its commanding APIs rather than any discrete input events.

Commanding relies on the ICommand interface, which enables the abstraction of a parameterized method call through its Execute method. In addition, you determine whether a method can be called prior to calling it with the CanExecute method.

Typically objects implement this interface to enable method calls on the objects through the use of XAML bindings. This is particularly useful in Model-View-ViewModel (MVVM) scenarios, as it allows models to expose commands to which controls such as buttons can be bound to without requiring additional code.

For more information see one of the following:

ICommand

ButtonBase.Command

Hyperlink.Command

The Handled Property in Event Data

Depending on your event handling strategy, you might want only one event handler to react to a bubbling mouse event. For example, if you have a specific MouseLeftButtonDown handler for one of the Rectangle objects, you might then not want the parent Canvas to also handle the event. For this scenario, use the Handled property in the event data.

The purpose of Handled in a Silverlight routed event data class is to influence the behavior of the Silverlight routed event system, to report that some other handler you had registered earlier on the event route has already acted. When you set Handled to true in an event handler, that event does not invoke the typical handlers that are attached further along the event route through an object tree.

The following example is a modification of the previous event-handler example, this time using Handled. The event handler sets Handled to true so that any handlers attached higher in the event route through the object tree will not be invoked. Note that whether the handler is called is a Silverlight event system behavior that keys off the Handled value in each event occurence's event data. If some other handler earlier in the route had already been invoked for an event occurence and set Handled to true in event data, then this handler example would not have been invoked for that event occurence.

void BubbleUpClick(object sender, MouseButtonEventArgs e)
{
    e.Handled = true;
    String msg = "x:y = " + e.GetPosition(null).ToString();
    msg += " from " + (e.OriginalSource as FrameworkElement).Name;
    statusTextBlock.Text = msg;
}
Private Sub BubbleUpClick(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
    e.Handled = True
    Dim fe As FrameworkElement = e.OriginalSource
    Dim msg As String = "x:y = " & e.GetPosition(Nothing).ToString()
    msg = msg & " from " & fe.Name
    statusTextBlock.Text = msg
End Sub

Whether to set Handled to true or not represents a conscious decision to stop the route. The exact meaning of whether any given input event is "Handled" is still up to you in the context of your application, but your decision to set Handled or not has a tangible effect on the further routing behavior of that particular input event. For more information on this concept, see Events Overview for Silverlight.

AddHandler and Already-Handled Mouse Events

You can use a special technique for attaching handlers that can act on events that already are marked handled. This technique uses the AddHandler method to register a handler, rather than using XAML attributes or language specific handler adding syntax such as += in C#. A limitation of this technique is that the AddHandler API takes a parameter of type RoutedEvent that identifies the routed event in question. Not all Silverlight routed events provide a RoutedEvent identifier, and this consideration thus affects which routed events can still be handled in the Handled case. The mouse events MouseLeftButtonDown, MouseLeftButtonUp, MouseRightButtonDown, MouseRightButtonUp and MouseWheel have routed event identifiers as fields on UIElement. The other mouse events (MouseEnter, MouseLeave, MouseMove) do not have routed event identifiers in Silverlight.

MouseEnter and MouseLeave Events

MouseEnter and MouseLeave events do not route. These events are only raised and can only be handled by the elements in which the mouse pointer enters or leaves. This event design is the same as in WPF, and also is patterned on how the Internet Explorer HTML DOM is designed.

If you want parent elements to be aware that child elements have received MouseEnter and MouseLeave events, you must do so as part of your own control or application logic. For control authors, overriding OnMouseEnter or OnMouseLeave can be helpful for this scenario.

Mouse Capture

You can use the CaptureMouse and ReleaseMouseCapture methods to enable and disable mouse capture. When an object has captured the mouse, it receives mouse input regardless of whether the mouse pointer is within its bounds.

For example, if an object retains mouse capture and the mouse pointer is moved outside the object's bounds, the object holding capture will continue to receive MouseMove events. The object that the mouse pointer is apparently over during this capture does not receive MouseMove events.

Mouse capture requires that the mouse button (the left mouse button in cases where there are left and right mouse buttons) is down during the entire time that the object intends to hold mouse capture. The moment the mouse button is released, mouse capture is lost by that object, and the mouse is not considered captured by any object. This condition raises the LostMouseCapture event on the object that originally held capture.

A major scenario for capturing the mouse is to implement visual positioning "drag-and-drop" operations, or variations thereof. For more information about capturing the mouse, see How to: Drag and Drop Objects in UI Layout.

Capturing the mouse potentially raises MouseEnter, if you capture the mouse from an element that does not already have the mouse pointer over its bounds.

Mouse Capture, Mouse Position, and MouseEnter/MouseLeave

LostMouseCapture uses MouseEventArgs and thus can report a mouse position. However, you should be aware that the event might fire in cases where the cause was neither a call to ReleaseMouseCapture nor a case where the user released the left mouse button within application bounds. For example, the browser host environment might take focus and thus capture in response to user action or its own action, or an action at operating system level (for example ALT+TAB in Windows) can take the input scope away from the Silverlight content scope entirely. In these cases the mouse position in the LostMouseCapture event data is a last known position and may not be suitable data for a UI action.

Also, always pairing a ReleaseMouseCapture call to MouseLeave on a particular UI element that is intended to be the capture source is not a robust design. This is because when LostMouseCapture reports the last known mouse position, a MouseEnter event is raised, then MouseEnter again as the mouse continues to move. Rather than call ReleaseMouseCapture on MouseLeave, you should instead listen for LostMouseCapture.

The Mouse as a Stylus

The mouse events can also be used to detect actions by a stylus device. This is because a mouse can be used instead of a stylus for input, serving as a stylus that happens to lack any variations in pressure and cannot be Inverted.

Multitouch Events Promoted to Mouse Events

Silverlight supports raw input events for multitouch. For platforms where multitouch is available, Silverlight is registered as the application to receive touch input, and it takes the WM_TOUCH messages it receives and generates the appropriate touch events. Users might be using multitouch devices to interact with applications that do not have specific multitouch handling. To account for this situation, multitouch events are also promoted as a simple mouse event. The primary touch point down is promoted as mouse left button down, the last touch point up is mouse up, and any movement between is potentially interpreted as mouse capture as well as mouse move. For more information, see Touch Input in Silverlight.

NoteNote:

Silverlight for Windows Phone handles manipulations and gestures through different techniques. For more information, see Input in Silverlight for Windows Phone.

Right-click Mouse Button Events

Silverlight supports events for right-click buttons on mouse devices. In order to capture a right-click mouse event, the client must be running a platform that is capable both by hardware and by operating system design of producing a right-click mouse input action. The MouseButtonEventArgs event data does not contain any information about which button is clicked. It is your responsibility as the handler to respond to the appropriate and distinct events that denote a left button click versus a right button click. Right button mouse click events are routed events, similar to the left click events, but do not share event data for purpose of Handled determination or otherwise relate to a left-click action. If the user presses both mouse buttons simultaneously, that produces two separate events.

NoteNote:

Applications targeting Silverlight 3 cannot use right-click mouse events.

Double-Click

Silverlight 5 introduces a ClickCount property to the MouseButtonEventArgs class. By reading the value of this property, you can assess whether the mouse button event represents a user double-click. The logic behind how ClickCount is set uses user preferences as set in the host operating system.

If you are targeting Silverlight 4 or earlier, you can still write your own code within a handler, or a helper function. The handler or function should determine whether the individual mouse button events constitute a double-click, determine whether both clicks occurred in an acceptable scope, and so on. Typical application code starts a Timer on the first mouse button handler invocation and then checks the timer on any subsequent mouse button handler invocations. This approach might also be useful for a Silverlight 5 application, if you want stricter control over the time window in which two click events should be coalesced to be considered a double-click

Mouse Events Outside the Visual Tree

Certain objects in Silverlight participate in a relationship with the primary visual tree that is conceptually like an overlay over the main visuals, and are not part of the usual parent-child relationships that connects all tree elements to the visual root. This is the case for any displayed Popup or ToolTip. If you want to detect mouse input that comes from a Popup or ToolTip, you should place the handlers on specific UI elements that are within the Popup or ToolTip and not the Popup or ToolTip elements themselves, and you should not rely on routing inside any compositing that is done for Popup or ToolTip content. This is because event routing for routed events works only along the main visual tree. Popup or ToolTip are not considered parents of subsidiary UI elements, and never receive the routed mouse event, even if are trying to use something like the Popup default background as the area to click.

Drag-Drop

Drag-drop is a mouse-related behavior, but it is not discussed in this topic. For more information on drag-drop in Silverlight, see AllowDrop and related events on UIElement such as DragEnter.

Mouse Events, Browser Hosts, and Operating Systems

If a Silverlight-based application is browser-hosted, the browser host plays a role in which mouse events it passes on to hosted content, including the Silverlight plug-in and Silverlight applications. At the next level of architecture, the operating system processes all input for the applications (including browser hosts) running under it, and this applies for out-of-browser applications also. When you handle input events, you should be aware that the nature of how input is reported in Silverlight can result in apparent "missing" or "extra" input-related events. For example, imagine a case where you have a handler for MouseLeftButtonDown as well as MouseLeftButtonUp at the root element of the application. The user clicks the left button somewhere in the application that produces an event, so your handler for MouseLeftButtonDown executes. Now, however, the user could move the mouse pointer entirely outside the Silverlight content area, and release the button. Or, the user could switch tasks away from the browser host with the result that the browser host is no longer displayed, and the user might release the mouse button thereafter. If your application logic always expected that a MouseLeftButtonDown was followed by MouseLeftButtonUp and that no further MouseLeftButtonDown could happen until then, your application could be in an unexpected state. As a general rule, you should design your application logic that interacts with mouse events to be robust for the possibility that not all input events from the user are always captured by Silverlight application code, for a variety of reasons.

Platform Notes

In Apple Safari, if an unhandled exception occurs in application event-handler code, no further mouse-related event handlers are called for the lifetime of the Silverlight plug-in. In other browsers, only the handler that contained the error will exit (usually with a scripting error returned to the browser); other errorless mouse event handlers can continue to function.