How do I create/handle IsMouseOverChanged

僤鯓⒐⒋嵵緔 提交于 2019-12-24 11:15:56

问题


I like the functionality of IsMouseDirectlyOverChanged, but it only works for the topmost elements. What I really want to do is monitor the IsMouseOver property of a control, regardless of its z-index, and receive notification when IsMouseOver is modified. If I owned this property, I could do INotifyPropertyChanged, but unfortunately it's owned by UIElement. Still learning the ropes of WPF, so maybe this is easy, but I'm not familiar with how to monitor properties that belong to parent classes. Unlike IsMouseDirectlyOver, IsMouseOver doesn't have a changed event attached.


回答1:


You can use styles to react to when IsMouseOver is changed.

<Window.Resources>
     <Style x:Key="RectStyle" TargetType="Rectangle">
          <Style.Triggers>
               <Trigger Property="IsMouseOver" Value="True">
                    <!-- react to property change here -->
               </Trigger>
          </Style.Triggers>
     </Style>
 </Window.Resources>

And later attach the style to an element:

<Rectangle Style="{StaticResource RecStyle}" Width="100" Height="100" Fill="Black" />

Edit:

If you want to call code from within a style, the solution is rather complex.

First, you have to create a custom UserControl class and give it an attached property. Whenever the attached property is changed, you can use the property changed callback. Here's the *.xaml.cs file, just keep the default .xaml file:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace ExampleApp
{
    /// <summary>
    /// Interaction logic for MouseOverWrapper.xaml
    /// </summary>
    public partial class MouseOverWrapper : UserControl
    {

        public static readonly DependencyProperty MouseIsOverProperty;

        static MouseOverWrapper()
        {
            MouseIsOverProperty = DependencyProperty.RegisterAttached(
                "MouseIsOver", typeof(bool), typeof(MouseOverWrapper),
                new FrameworkPropertyMetadata(false, OnMouseIsOverChanged));
        }

        public static bool GetMouseIsOver(UIElement element)
        {
            return (bool)element.GetValue(MouseIsOverProperty);
        }

        public static void SetMouseIsOver(UIElement target, bool value)
        {
            target.SetValue(MouseIsOverProperty, value);
        }

        private static void OnMouseIsOverChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            // handle code here. example:
            if ((bool)e.NewValue == true)
                ((Rectangle)d).Fill = Brushes.Yellow;
            else
                ((Rectangle)d).Fill = Brushes.Black;
        }

        public MouseOverWrapper()
        {
            InitializeComponent();
        }
    }
}

You'll then have to wrap the elements you want to react to in your custom control and make the style change the attached property of that custom control. Example:

<Window x:Class="ExampleApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:ExampleApp"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <Style x:Key="RecStyle" TargetType="Rectangle">
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="local:MouseOverWrapper.MouseIsOver" Value="True" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <local:MouseOverWrapper>
        <Rectangle Style="{StaticResource RecStyle}" Width="100" Height="100" Fill="Black" />
    </local:MouseOverWrapper>
</Window>

Add all your code into the OnMouseOverIsChanged function, and this should work.




回答2:


I see there is an accepted solution, I just wanted to share my opinion. In my case I have a Label in a Usercontrol and I needed to react on Mouse is over. For me the MouseEnter and MouseLeave events fire, so I can handle them. I have the label defined in Code Behind (since I place it programatically on runtime) and just added standard Events of the label object. IsMouseDirectlyOverChanged did not work for me, since I'm hovering over the Usercontrol. This also works if there is another Control overlapping. So maybe this doesn't fit your situation, maybe it does :-)
I wanted to paste the xaml as well, but it seems I didn't get the markdown-thing :-)

...
    Private Sub Rectangle1_MouseEnter(sender As Object, e As System.Windows.Input.MouseEventArgs) Handles Rectangle1.MouseEnter, Rectangle2.MouseEnter
        Dim s As Rectangle = sender
        s.Fill = Brushes.Red
    End Sub

    Private Sub Rectangle1_MouseLeave(sender As Object, e As System.Windows.Input.MouseEventArgs) Handles Rectangle1.MouseLeave, Rectangle2.MouseLeave
        Dim s As Rectangle = sender
        s.Fill = Brushes.Green
    End Sub
...

BR, D



来源:https://stackoverflow.com/questions/10985993/how-do-i-create-handle-ismouseoverchanged

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!