2009-07-15 9 views

risposta

4

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

questo link risolto il problema, non ho provato l'idea originale.

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

dove locale: MyTreeViewHelper.IsMouseDirectlyOverItem è allegata proprietà

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); 

      } 
     } 
    } 
} 
+0

Se questo ha risolto il tuo problema, contrassegnalo come risposta. – jpierson

-1

Sembra l'evento giusto. Una cosa che puoi fare per prevenire gli eventi di MouseOver è controllare gli eventi di MouseOver per TreeViewItems. Se RoutedEventArgs.OriginalSource non è uguale al genitore, è sufficiente restituire e gestire manualmente i gestori di eventi.

public void TreeViewItem_MouseOver(object sender, RoutedEventArgs e) 
{ 
    if (sender != e.OriginalSource) return; 
} 
+0

troppo male non c'è nessun evento MouseOver per un oggetto TreeView ... – RoelF

+0

Mi dispiace. Realmente ho realizzato dopo averlo scritto che lavoriamo con una classe TreeViewItem sovrascritta che implementa MouseOver. Se effettivamente funziona, la soluzione di Mahop sarebbe elegantemente semplice. –

1

Ok - ho avuto il problema e ho sprecato quasi un giorno risolverlo ... Tutto quello che devi fare è quello di prenditi cura di questo dal codice sottostante. Per esempio:

In XAML:

<TreeViewItem Header="{Binding diskName}" 
Background="Transparent" Mouse.MouseEnter="changeBackground"> 

E nel file cs:

private void changeBackground(object sender, MouseEventArgs e) 
{ 
     TreeViewItem t = (TreeViewItem)sender; 
     t.Background = (SolidColorBrush)(new BrushConverter().ConvertFrom("#CCE8FF")); 
     e.Handled = false; 
} 

Che dovrebbe farlo. In bocca al lupo!