#670 – Getting the Mouse Position Relative to a Specific Element

When you use the Mouse.GetPosition method or MouseButtonEventsArgs.GetPosition method to get the mouse position, you specify that you want the mouse position relative to a particular element.

If you pass a null value into the GetPosition method, you indicate that you want the mouse position relative to the containing window.    However, you can also pass a reference to a control that implements the IInputElement interface.  Since UIElement implements IInputElement, you can pass in a reference to any user interface element.

In the example below, on mouse movement, we display the coordinates of the mouse position relative to the main window, as well as relative to a Button.

        private void win1_MouseMove_1(object sender, MouseEventArgs e)
        {
            Point p = e.GetPosition(null);
            MousePosText = string.Format("GetPosition(null): X = {0}, Y = {1}", p.X, p.Y);

            p = e.GetPosition(btn1);
            MousePosText2 = string.Format("GetPosition(btn1): X = {0}, Y = {1}", p.X, p.Y);
        }



#669 – Retrieving the Mouse’s Current Position in an Event Handler

You can use the static Mouse.GetPosition method anywhere in your code to retrieve the current position of your mouse.

You can also access the mouse position through either the MouseButtonEventArgs or MouseEventArgs object passed in to an event handler for any of the mouse-related events.

In the example below, we use the MouseButtonEventArgs.GetPosition and MouseEventArgs.GetPosition methods in the handlers to get the mouse’s position and to update a related label.

        private void win1_MouseLeftButtonDown_1(object sender, MouseButtonEventArgs e)
        {
            Point p = e.GetPosition(null);
            MousePosTextLastClick = string.Format("Last click at X = {0}, Y = {1}", p.X, p.Y);
        }

        private void win1_MouseMove_1(object sender, MouseEventArgs e)
        {
            Point p = e.GetPosition(null);
            MousePosText = string.Format("X = {0}, Y = {1}", p.X, p.Y);
        }


#668 – Retrieving the Mouse’s Current Position

You can retrieve the current position of the mouse at any time using the Mouse.GetPosition method.  Mouse is a static class that provides information about the mouse through a variety of static methods.

The GetPosition method returns a Point object, which contains the and Y position of the mouse, relative to a specified user interface element.

In the example below, we call the GetPosition method and then set a property to report the mouse’s position.  (We’ll bind a label’s Content to this property).  Passing null to GetPosition means that we want the position relative to the top-level window.

        private void win1_MouseLeftButtonDown_1(object sender, MouseButtonEventArgs e)
        {
            ReportMousePosition();
        }

        // Can be called at any time (not just from event handler)
        public void ReportMousePosition()
        {
            Point p = Mouse.GetPosition(null);

            MousePosText = string.Format("X = {0}, Y = {1}", p.X, p.Y);
        }



#667 – IsMouseOver vs. IsMouseDirectlyOver

The IsMouseOver property for a user interface element indicates whether the mouse is currently located over the element or any of its children.  For example, for a Button contained in a StackPanel, when the user moves the mouse over the ButtonIsMouseOver will be true for both the Button and the StackPanel.

The IsMouseDirectlyOver, on the other hand, indicates whether the mouse is over a control and not over any of its children.

In the example below, when the mouse is over the button, the StackPanel’s IsMouseOver property is true, but its IsMouseDirectlyOver property is false.

 

Notice that IsMouseDirectlyOver is also false for the Button.  This is because the mouse is actually pointing to some child element within the Button element.

If we move the mouse back off the Button, but still within the StackPanel, its IsMouseDirectlyOver property becomes true.

#666 – Using a Trigger to React to the Mouse Being Over a Control

You can perform some action when the user moves the mouse over a user interface element by defining event handlers for the MouseEnter and MouseLeave events for the element.

If the action that you’re performing is something that can be expressed in XAML (like setting a property value), it’s more elegant to use a trigger to react to the mouse movement.

You can define a property trigger for the IsMouseOver property, setting new values for one or more of the Button’s properties when the mouse is over the Button.

    <StackPanel Margin="20" >
        <Button HorizontalAlignment="Center" Padding="10,5">
            <Button.Style>
                <Style TargetType="Button">
                    <Setter Property="Content" Value="Click Me"/>
                    <Style.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Button.Content" Value="!! CLICK Me !!"/>
                            <Setter Property="FontWeight" Value="Bold"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </Button.Style>
        </Button>
    </StackPanel>



Note that when you move the mouse off of the Button, the Content and FontWeight properties both revert back to their original values.

#665 – Reacting to MouseEnter / MouseLeave Events

If there’s some action that you want to take when a user hovers over a control, you can add handlers for the MouseEnter and MouseLeave events.

For example, let’s say that you want to change a Button’s text when the user hovers over the button.  You could define handlers for the MouseEnter and MouseLeave events in XAML:

    <StackPanel Margin="20" >
        <Button Content="Click Me" HorizontalAlignment="Center" Padding="10,5"
                MouseEnter="Button_MouseEnter_1" MouseLeave="Button_MouseLeave_1"/>
    </StackPanel>

Then, in your handlers, you could set (or restore) the Button’s Content property.

        private void Button_MouseEnter_1(object sender, MouseEventArgs e)
        {
            ((Button)sender).Content = "CLICK Me";
        }

        private void Button_MouseLeave_1(object sender, MouseEventArgs e)
        {
            ((Button)sender).Content = "Click Me";
        }



We’ll see next time that there’s a much easier way to do this, using a trigger.

#664 – MouseEnter and MouseLeave Events

An UIElement will fire a MouseEnter event when its IsMouseOver property becomes true.  It will fire a MouseLeave event when its IsMouseOver property becomes false.

These are both direct events, i.e. they don’t bubble or tunnel, but fire only for the UIElement whose IsMouseOver property is changing.

Suppose that we have a Button contained in a StackPanel that is in a Window.

If we move the mouse into the area of the Window that is not covered by the StackPanel, the MouseEnter for the Window will fire.

If we then move into the StackPanel, we’ll get a MouseEnter for the StackPanel, but we will not get a MouseLeave event for the Window–because the pointer is still located in the Window.

 

Moving over the Button fires its MouseEnter event.

 

Moving out of the Button along its top edge triggers MouseLeave events for the Button, the StackPanel, and the Window.

 

#663 – How IsMouseOver Works for Nested Elements

The IsMouseOver property for a user interface element indicates whether the mouse is currently over the element.

When an element is contained within another element in the logical tree, then IsMouseOver will be true for both the lower-level element and for any elements higher up in the logical tree.

Suppose that we have a Button in a StackPanel which is inside a Window.

<Window Name="win1">
    <StackPanel Name="sp1" Background="Pink" Margin="20,0">
        <Button Name="btn1" Content="Click Me" HorizontalAlignment="Center" Padding="10,5"/>
    </StackPanel>
</Window>

If the mouse is in the application’s Window, but outside of the StackPanelIsMouseOver will be true only for the Window.

If we move the mouse into the StackPanel, but not over the ButtonIsMouseOver will be true for both the StackPanel and the Window.

Finally, moving the mouse over the Button results in IsMouseOver being true for all three elements.

#662 – IsMouseOver Property

Every UIElement object has an IsMouseOver property that indicates whether or not the mouse is currently located over the element.

In the example below, we define a Label whose content is bound to the current state of the IsMouseOver property for a Button.

    <StackPanel Margin="20">
        <Button Name="btn1" Content="Move Mouse Over Me !" HorizontalAlignment="Center" Padding="10,5"/>
        <Label Content="{Binding ElementName=btn1, Path=IsMouseOver}" Foreground="Green"/>
    </StackPanel>


#661 – ButtonBase.Click Event vs. Mouse Click Events

Controls that derive from ButtonBase, like the standard Button, inherit a Click event that fires when user clicks on the button using the left mouse button.

Because ButtonBase inherits from UIElement, a Button will also have access to all of the mouse button events defined for UIElement.

Because the Button does something in response to button presses, it swallows the bubbling events (e.g. MouseLeftButtonDown and MouseDown).  You can still detect these lower level button press events by adding handlers for the tunneling events (e.g. PreviewMouseLeftButtonDown and PreviewMouseDown).  You can also request that your handlers are called even for already-handled events by specifying a handler in code and setting the handledEventsToo parameter to true.

For a left-click on a Button, you’ll normally see click-related events in the following order:

  • UIElement.PreviewMouseLeftButtonDown 
  • UIElement.PreviewMouseDown
  • UIElement.PreviewMouseLeftButtonUp
  • UIElement.PreviewMouseUp
  • ButtonBase.Click