我明白为什么会这样。父TreeViewItem的边界框包含其子边框,因此当我在TreeViewItem上进行鼠标悬停时,树中的所有父节点也会被覆盖。除了我应该使用的IsMouseOver之外还有什么东西吗?
答案 0 :(得分:5)
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>
where 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);
}
}
}
}
答案 1 :(得分:1)
好的 - 我遇到了你的问题,我浪费了将近一天的时间来解决它... 您需要做的就是从后面的代码中解决这个问题。 例如:
在XAML中:
<TreeViewItem Header="{Binding diskName}"
Background="Transparent" Mouse.MouseEnter="changeBackground">
在cs文件中:
private void changeBackground(object sender, MouseEventArgs e)
{
TreeViewItem t = (TreeViewItem)sender;
t.Background = (SolidColorBrush)(new BrushConverter().ConvertFrom("#CCE8FF"));
e.Handled = false;
}
应该这样做。祝你好运!
答案 2 :(得分:0)
此link为我提供了一个很好的解决方案。
有效地,您可以覆盖ControlTemplate并将SourceName
设置器的IsMouseOver
指定为TreeViewItem
的标头部分。因此,是的,从技术上讲,您将鼠标悬停在子TreeViewItems
和父<table #table mat-table [dataSource]="dataSource">
<ng-container matColumnDef="empty1">
<th mat-header-cell *matHeaderCellDef style="text-align: center"> </th>
</ng-container>
<ng-container matColumnDef="empty2">
<th mat-header-cell *matHeaderCellDef style="text-align: center"> </th>
</ng-container>
<ng-container matColumnDef="identifier">
<th mat-header-cell *matHeaderCellDef colspan="3" style="text-align: center"> Column Label </th>
</ng-container>
</table>
上,但是触发器仅针对光标位于标题上方的项目触发。
答案 3 :(得分:-1)
这听起来像是正确的事件。您可以做的一件事就是阻止MouseOver事件检查TreeViewItems的MouseOver事件。如果您的RoutedEventArgs.OriginalSource不等于父级,只需手动返回并管理您的事件处理程序。
public void TreeViewItem_MouseOver(object sender, RoutedEventArgs e)
{
if (sender != e.OriginalSource) return;
}