我了解为什么会这样。父TreeViewItem的边界框包括其子项的边界框,因此,当我将鼠标悬停在TreeViewItem上时,也将鼠标悬停在树中的所有父项上。我应该使用IsMouseOver以外的东西吗?

最佳答案

http://blogs.msdn.com/mikehillberg/archive/2006/09/21/MyTreeViewHelperIsMouseDirectlyOverItem.aspx

此链接解决了问题,我没有尝试使用“原始来源”的想法。

  <Style TargetType="TreeViewItem">
    <Style.Triggers>
      <Trigger Property="local:MyTreeViewHelper.IsMouseDirectlyOverItem" Value="True">
        <Setter Property="Background" Value="Green" />
      </Trigger>
    </Style.Triggers>
  </Style>

其中local:MyTreeViewHelper.IsMouseDirectlyOverItem附加属性
public static class MyTreeViewHelper
{
    //
    // The TreeViewItem that the mouse is currently directly over (or null).
    //
    private static TreeViewItem _currentItem = null;

    //
    // IsMouseDirectlyOverItem:  A DependencyProperty that will be true only on the
    // TreeViewItem that the mouse is directly over.  I.e., this won't be set on that
    // parent item.
    //
    // This is the only public member, and is read-only.
    //

    // The property key (since this is a read-only DP)
    private static readonly DependencyPropertyKey IsMouseDirectlyOverItemKey =
        DependencyProperty.RegisterAttachedReadOnly("IsMouseDirectlyOverItem",
                                            typeof(bool),
                                            typeof(MyTreeViewHelper),
                                            new FrameworkPropertyMetadata(null, new CoerceValueCallback(CalculateIsMouseDirectlyOverItem)));

    // The DP itself
    public static readonly DependencyProperty IsMouseDirectlyOverItemProperty =
        IsMouseDirectlyOverItemKey.DependencyProperty;

    // A strongly-typed getter for the property.
    public static bool GetIsMouseDirectlyOverItem(DependencyObject obj)
    {
        return (bool)obj.GetValue(IsMouseDirectlyOverItemProperty);
    }

    // A coercion method for the property
    private static object CalculateIsMouseDirectlyOverItem(DependencyObject item, object value)
    {
        // This method is called when the IsMouseDirectlyOver property is being calculated
        // for a TreeViewItem.

        if (item == _currentItem)
            return true;
        else
            return false;
    }

    //
    // UpdateOverItem:  A private RoutedEvent used to find the nearest encapsulating
    // TreeViewItem to the mouse's current position.
    //

    private static readonly RoutedEvent UpdateOverItemEvent = EventManager.RegisterRoutedEvent(
        "UpdateOverItem", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MyTreeViewHelper));

    //
    // Class constructor
    //

    static MyTreeViewHelper()
    {
        // Get all Mouse enter/leave events for TreeViewItem.
        EventManager.RegisterClassHandler(typeof(TreeViewItem), TreeViewItem.MouseEnterEvent, new MouseEventHandler(OnMouseTransition), true);
        EventManager.RegisterClassHandler(typeof(TreeViewItem), TreeViewItem.MouseLeaveEvent, new MouseEventHandler(OnMouseTransition), true);

        // Listen for the UpdateOverItemEvent on all TreeViewItem's.
        EventManager.RegisterClassHandler(typeof(TreeViewItem), UpdateOverItemEvent, new RoutedEventHandler(OnUpdateOverItem));
    }


    //
    // OnUpdateOverItem:  This method is a listener for the UpdateOverItemEvent.  When it is received,
    // it means that the sender is the closest TreeViewItem to the mouse (closest in the sense of the tree,
    // not geographically).

    static void OnUpdateOverItem(object sender, RoutedEventArgs args)
    {
        // Mark this object as the tree view item over which the mouse
        // is currently positioned.
        _currentItem = sender as TreeViewItem;

        // Tell that item to re-calculate the IsMouseDirectlyOverItem property
        _currentItem.InvalidateProperty(IsMouseDirectlyOverItemProperty);

        // Prevent this event from notifying other tree view items higher in the tree.
        args.Handled = true;
    }

    //
    // OnMouseTransition:  This method is a listener for both the MouseEnter event and
    // the MouseLeave event on TreeViewItems.  It updates the _currentItem, and updates
    // the IsMouseDirectlyOverItem property on the previous TreeViewItem and the new
    // TreeViewItem.

    static void OnMouseTransition(object sender, MouseEventArgs args)
    {
        lock (IsMouseDirectlyOverItemProperty)
        {
            if (_currentItem != null)
            {
                // Tell the item that previously had the mouse that it no longer does.
                DependencyObject oldItem = _currentItem;
                _currentItem = null;
                oldItem.InvalidateProperty(IsMouseDirectlyOverItemProperty);
            }

            // Get the element that is currently under the mouse.
            IInputElement currentPosition = Mouse.DirectlyOver;

            // See if the mouse is still over something (any element, not just a tree view item).
            if (currentPosition != null)
            {
                // Yes, the mouse is over something.
                // Raise an event from that point.  If a TreeViewItem is anywhere above this point
                // in the tree, it will receive this event and update _currentItem.

                RoutedEventArgs newItemArgs = new RoutedEventArgs(UpdateOverItemEvent);
                currentPosition.RaiseEvent(newItemArgs);

            }
        }
    }
}

关于wpf - 如何使TreeViewItem上的IsMouseOver的WPF触发器不影响moused-over控件的所有父级?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1131161/

10-11 06:54