.net 突出显示正在拖动的TreeView项目

.net 突出显示正在拖动的TreeView项目,.net,wpf,xaml,drag-and-drop,treeview,.net,Wpf,Xaml,Drag And Drop,Treeview,在我的应用程序中,我有一个允许拖放的树状视图。我所有的功能都工作得很好,但是当它被拖过来时,我很难突出显示TreeViewItem。这是我的treeview项目的风格。拖动时IsMouseOver触发器不工作,因为拖动似乎会阻止其他鼠标事件。有人能帮我在拖动treeview项目时触发相同的边框更改吗 <Style x:Key="TreeViewItemStyle" TargetType="{x:Type TreeViewItem}"> <Setter Property

在我的应用程序中,我有一个允许拖放的树状视图。我所有的功能都工作得很好,但是当它被拖过来时,我很难突出显示TreeViewItem。这是我的treeview项目的风格。拖动时IsMouseOver触发器不工作,因为拖动似乎会阻止其他鼠标事件。有人能帮我在拖动treeview项目时触发相同的边框更改吗

<Style x:Key="TreeViewItemStyle" TargetType="{x:Type TreeViewItem}"> 
    <Setter Property="Template"> 
        <Setter.Value> 
            <ControlTemplate TargetType="{x:Type TreeViewItem}"> 
                <Grid> 
                    <Grid.ColumnDefinitions> 
                        <ColumnDefinition MinWidth="19" Width="Auto"/> 
                        <ColumnDefinition Width="Auto"/> 
                        <ColumnDefinition Width="*"/> 
                    </Grid.ColumnDefinitions> 
                    <Grid.RowDefinitions> 
                        <RowDefinition Height="Auto"/> 
                        <RowDefinition/> 
                    </Grid.RowDefinitions> 
                    <ToggleButton  
                        x:Name="PART_Expander" 
                        Style="{StaticResource ExpandCollapseToggleStyle}" 
                        IsChecked="{Binding Path=IsExpanded, RelativeSource={RelativeSource TemplatedParent}}" 
                        ClickMode="Press" 
                        /> 
                    <Border 
                        x:Name="OuterBorder"  
                        Grid.Column="1" 
                        SnapsToDevicePixels="True" 
                        BorderThickness="1"  
                        CornerRadius="3"  
                        BorderBrush="Transparent"  
                        Background="Transparent" 
                        > 
                        <Border  
                            x:Name="InnerBorder"  
                            SnapsToDevicePixels="True" 
                            BorderThickness="1"  
                            CornerRadius="2"  
                            BorderBrush="Transparent"  
                            Background="Transparent" 
                            > 
                            <ContentPresenter 
                                x:Name="PART_Content" 
                                ContentSource="Header" 
                                HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                                /> 
                        </Border> 
                    </Border> 
                    <ItemsPresenter 
                        x:Name="PART_ItemsHost" 
                        Grid.Row="1" 
                        Grid.Column="1" 
                        Grid.ColumnSpan="2" 
                        /> 
                </Grid> 
                <ControlTemplate.Triggers> 
                    <Trigger Property="IsMouseOver" SourceName="OuterBorder" Value="True"> 
                        <Setter TargetName="OuterBorder" Property="BorderBrush" Value="Blue" /> 
                        <Setter TargetName="OuterBorder" Property="Background" Value="Red" /> 
                        <Setter TargetName="InnerBorder" Property="BorderBrush" Value="White" /> 
                    </Trigger> 
                    <MultiTrigger> 
                </ControlTemplate.Triggers> 
            </ControlTemplate> 
        </Setter.Value> 
    </Setter> 
</Style>

查看事件(可能还有DragEnter/DragLeave),而不是IsMouseOver。

我正在为此使用附加属性,然后在我的xaml文件中使用该属性更改树状视图项的背景色:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace SKNotes.Utilities
{
    /// <summary>
    /// Implements an attached property used for styling TreeViewItems when
    /// they're a possible drop target.
    /// </summary>
    public static class TreeViewDropHighlighter
    {
        #region private variables
        /// <summary>
        /// the TreeViewItem that is the current drop target
        /// </summary>
        private static TreeViewItem _currentItem = null;

        /// <summary>
        /// Indicates whether the current TreeViewItem is a possible
        /// drop target
        /// </summary>
        private static bool _dropPossible;
        #endregion

        #region IsPossibleDropTarget
        /// <summary>
        /// Property key (since this is a read-only DP) for the IsPossibleDropTarget property.
        /// </summary>
        private static readonly DependencyPropertyKey IsPossibleDropTargetKey = 
                                    DependencyProperty.RegisterAttachedReadOnly(
                                        "IsPossibleDropTarget",
                                        typeof( bool ),
                                        typeof( TreeViewDropHighlighter ),
                                        new FrameworkPropertyMetadata( null,
                                            new CoerceValueCallback( CalculateIsPossibleDropTarget ) ) );


        /// <summary>
        /// Dependency Property IsPossibleDropTarget.
        /// Is true if the TreeViewItem is a possible drop target (i.e., if it would receive
        /// the OnDrop event if the mouse button is released right now).
        /// </summary>
        public static readonly DependencyProperty IsPossibleDropTargetProperty = IsPossibleDropTargetKey.DependencyProperty;

        /// <summary>
        /// Getter for IsPossibleDropTarget
        /// </summary>
        public static bool GetIsPossibleDropTarget( DependencyObject obj )
        {
            return (bool)obj.GetValue( IsPossibleDropTargetProperty );
        }

        /// <summary>
        /// Coercion method which calculates the IsPossibleDropTarget property.
        /// </summary>
        private static object CalculateIsPossibleDropTarget( DependencyObject item, object value )
        {
            if ( ( item == _currentItem ) && ( _dropPossible ) )
                return true;
            else
                return false;
        }
        #endregion

        /// <summary>
        /// Initializes the <see cref="TreeViewDropHighlighter"/> class.
        /// </summary>
        static TreeViewDropHighlighter( )
        {
            // Get all drag enter/leave events for TreeViewItem.
            EventManager.RegisterClassHandler( typeof( TreeViewItem ),
                                      TreeViewItem.PreviewDragEnterEvent,
                                      new DragEventHandler( OnDragEvent ), true );
            EventManager.RegisterClassHandler( typeof( TreeViewItem ),
                                      TreeViewItem.PreviewDragLeaveEvent,
                                      new DragEventHandler( OnDragLeave ), true );
            EventManager.RegisterClassHandler( typeof( TreeViewItem ),
                                      TreeViewItem.PreviewDragOverEvent,
                                      new DragEventHandler( OnDragEvent ), true );
        }

        #region event handlers
        /// <summary>
        /// Called when an item is dragged over the TreeViewItem.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="args">The <see cref="System.Windows.DragEventArgs"/> instance containing the event data.</param>
        static void OnDragEvent( object sender, DragEventArgs args )
        {
            lock ( IsPossibleDropTargetProperty )
            {
                _dropPossible = false;

                if ( _currentItem != null )
                {
                    // Tell the item that previously had the mouse that it no longer does.
                    DependencyObject oldItem = _currentItem;
                    _currentItem = null;
                    oldItem.InvalidateProperty( IsPossibleDropTargetProperty );
                }

                if ( args.Effects != DragDropEffects.None )
                {
                    _dropPossible = true;
                }

                TreeViewItem tvi = sender as TreeViewItem;
                if ( tvi != null )
                {
                    _currentItem = tvi;
                    // Tell that item to re-calculate the IsPossibleDropTarget property
                    _currentItem.InvalidateProperty( IsPossibleDropTargetProperty );
                }
            }
        }

        /// <summary>
        /// Called when the drag cursor leaves the TreeViewItem
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="args">The <see cref="System.Windows.DragEventArgs"/> instance containing the event data.</param>
        static void OnDragLeave( object sender, DragEventArgs args )
        {
            lock ( IsPossibleDropTargetProperty )
            {
                _dropPossible = false;

                if ( _currentItem != null )
                {
                    // Tell the item that previously had the mouse that it no longer does.
                    DependencyObject oldItem = _currentItem;
                    _currentItem = null;
                    oldItem.InvalidateProperty( IsPossibleDropTargetProperty );
                }

                TreeViewItem tvi = sender as TreeViewItem;
                if ( tvi != null )
                {
                    _currentItem = tvi;
                    tvi.InvalidateProperty( IsPossibleDropTargetProperty );
                }
            }
        }
        #endregion
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Input;
命名空间SKNotes.Utilities
{
/// 
///在以下情况下实现用于设置TreeView项样式的附加属性:
///他们是可能的坠落目标。
/// 
公共静态类TreeViewer
{
#区域私有变量
/// 
///当前丢弃目标的TreeView项
/// 
私有静态TreeViewItem\u currentItem=null;
/// 
///指示当前TreeViewItem是否是可能的
///下降目标
/// 
私有静态boolu可能;
#端区
#区域是可能的下降目标
/// 
///IsPossibleDropTarget属性的属性键(因为这是只读DP)。
/// 
私有静态只读依赖项PropertyKey IsPossibleDropTargetKey=
DependencyProperty.RegisterAttacheOnly(
“IsPossibleDropTarget”,
类型(bool),
类型(TreeViewDropHighlighter),
新的FrameworkPropertyMetadata(空,
新的强制值回调(CalculateIsPossibleDropTarget));
/// 
///依赖项属性IsPossibleDropTarget。
///如果TreeViewItem是一个可能的丢弃目标(即,如果它将接收
///如果现在释放鼠标按钮,则显示OnDrop事件)。
/// 
公共静态只读DependencyProperty IsPossibleDropTargetProperty=IsPossibleDropTargetKey.DependencyProperty;
/// 
///IsPossibleDropTarget的Getter
/// 
公共静态bool GetIsPossibleDropTarget(DependencyObject obj)
{
返回(bool)对象GetValue(IsPossibleDropTargetProperty);
}
/// 
///计算IsPossibleDropTarget属性的强制方法。
/// 
私有静态对象CalculatesPossibledRopTarget(DependencyObject项,对象值)
{
如果((项目==\u当前项目)和(\u可能))
返回true;
其他的
返回false;
}
#端区
/// 
///初始化类。
/// 
静态树形荧光灯()
{
//获取TreeViewItem的所有拖放输入/离开事件。
RegisterClassHandler(typeof(treevieItem),
TreeViewItem.PreviewDragEnterEvent,
新DragEventHandler(OnDragEvent),正确;
RegisterClassHandler(typeof(treevieItem),
TreeViewItem.PreviewDragLeaveEvent,
新DragEventHandler(Ondragleef),正确;
RegisterClassHandler(typeof(treevieItem),
TreeViewItem.PreviewDragOverEvent,
新DragEventHandler(OnDragEvent),正确;
}
#区域事件处理程序
/// 
///在将项拖到TreeViewItem上时调用。
/// 
///发送者。
///包含事件数据的实例。
静态无效OnDragEvent(对象发送方、DragEventArgs参数)
{
锁(IsPossibleDropTargetProperty)
{
_dropposable=false;
如果(_currentItem!=null)
{
//告诉以前有鼠标的项目它不再有鼠标了。
DependencyObject oldItem=\u currentItem;
_currentItem=null;
oldItem.InvalidateProperty(IsPossibleDropTargetProperty);
}
if(args.Effects!=DragDropEffects.None)
{
_可能=真;
}
TreeViewItem tvi=发送方作为TreeViewItem;
如果(tvi!=null)
{
_currentItem=tvi;
//告诉该项重新计算IsPossibleDropTarget属性
_currentItem.InvalidateProperty(IsPossibleDropTargetProperty);
}
}
}
/// 
///当拖动光标离开Tr时调用
    <TreeView.ItemContainerStyle>
        <Style TargetType="{x:Type TreeViewItem}">
            <Setter Property="FontWeight" Value="Normal" />
            <Style.Triggers>
                <Trigger Property="utils:TreeViewDropHighlighter.IsPossibleDropTarget" Value="True">
                    <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </TreeView.ItemContainerStyle>
Namespace SKNotes.Utilities

''' <summary>
''' Implements an attached property used for styling TreeViewItems when
''' they are a possible drop target.
''' </summary>
Public Class TreeViewDropHighlighter

    ''' <summary>
    ''' The TreeViewItem that is the current drop target
    ''' </summary>
    Private Shared _CurrentItem As TreeViewItem = Nothing

    ''' <summary>
    ''' Indicates whether the current TreeView Item is a possible drop target
    ''' </summary>
    ''' <remarks></remarks>
    Private Shared _DropPossible As Boolean

    ''' <summary>
    ''' Property Key (since this is a read only DP) for the IsPossibleDropTarget property.
    ''' </summary>
    ''' <remarks></remarks>
    Private Shared ReadOnly IsPossibleDropTargetKey As DependencyPropertyKey = _
                                            DependencyProperty.RegisterAttachedReadOnly _
                                            ( _
                                                "IsPossibleDropTarget", _
                                                GetType(Boolean), _
                                                GetType(TreeViewDropHighlighter), _
                                                New FrameworkPropertyMetadata(Nothing, _
                                                                                New CoerceValueCallback(AddressOf CalculateIsPossibleDropTarget)
                                                                                )
                                            )
    ''' <summary>
    ''' Dependency Property IsPossibleDropTarget.
    ''' Is true if the TreeViewItem is a possible drop target (ie, if it would receive the 
    ''' OnDrop even if the mouse button is release right now).
    ''' </summary>
    ''' <remarks></remarks>
    Public Shared ReadOnly IsPossibleDropTargetProperty As DependencyProperty = IsPossibleDropTargetKey.DependencyProperty

    ''' <summary>
    ''' Getter for IsPossibleDropTarget
    ''' </summary>
    Public Shared Function GetIsPossibleDropTarget(ByVal obj As DependencyObject) As Boolean
        Return CBool(obj.GetValue(IsPossibleDropTargetProperty))
    End Function

    ''' <summary>
    ''' Coercion method which calculates the IsPossibleDropTarget property
    ''' </summary>
    Private Shared Function CalculateIsPossibleDropTarget(item As DependencyObject, value As Object) As Object
        If item.Equals(_CurrentItem) And _
           _DropPossible Then
            Return True
        Else
            Return False
        End If
    End Function

    ''' <summary>
    ''' Initializes the TreeViewDropHighlighter class
    ''' </summary>
    Shared Sub New()
        EventManager.RegisterClassHandler(GetType(TreeViewItem), _
                                            TreeViewItem.PreviewDragEnterEvent, _
                                            New DragEventHandler(AddressOf OnDragEvent), True)
        EventManager.RegisterClassHandler(GetType(TreeViewItem), _
                                            TreeViewItem.PreviewDragLeaveEvent,
                                            New DragEventHandler(AddressOf OnDragLeave), True)
        EventManager.RegisterClassHandler(GetType(TreeViewItem), _
                                            TreeViewItem.PreviewDragOverEvent, _
                                            New DragEventHandler(AddressOf OnDragEvent), True)
    End Sub

    ''' <summary>
    ''' Called when an item is dragged over the TreeView Item
    ''' </summary>
    ''' <param name="sender">The sender</param>
    ''' <param name="args">The System.Windows.DragEventArgs instance containing the event data</param>
    ''' <remarks></remarks>
    Shared Sub OnDragEvent(sender As Object, args As DragEventArgs)
        SyncLock (IsPossibleDropTargetProperty)
            _DropPossible = False
            If Not IsNothing(_CurrentItem) Then
                'Tell the item that previously had the mouse that it no longer does.
                Dim OldItem As DependencyObject = _CurrentItem
                _CurrentItem = Nothing
                OldItem.InvalidateProperty(IsPossibleDropTargetProperty)
            End If

            If args.Effects <> DragDropEffects.None Then
                _DropPossible = True
            End If

            Dim tvi As TreeViewItem = CType(sender, TreeViewItem)
            If Not IsNothing(tvi) Then
                _CurrentItem = tvi
                'Tell that item to recalculate the IsPossibleDropTarget property
                _CurrentItem.InvalidateProperty(IsPossibleDropTargetProperty)
            End If
        End SyncLock
    End Sub

    Shared Sub OnDragLeave(sender As Object, args As DragEventArgs)

        SyncLock (IsPossibleDropTargetProperty)
            _DropPossible = False
            If Not IsNothing(_CurrentItem) Then
                'Tell the item that previously had the mouse that it no longer does
                Dim OldItem As DependencyObject = _CurrentItem
                _CurrentItem = Nothing
                OldItem.InvalidateProperty(IsPossibleDropTargetProperty)
            End If

            Dim tvi As TreeViewItem = CType(sender, TreeViewItem)
            If Not IsNothing(tvi) Then
                _CurrentItem = tvi
                tvi.InvalidateProperty(IsPossibleDropTargetProperty)
            End If

        End SyncLock

    End Sub

End Class
static void OnDragDrop(object sender, DragEventArgs args)
{
    lock (IsPossibleDropTargetProperty)
    {
        _dropPossible = false;

        if (_currentItem != null)
        {
            _currentItem.InvalidateProperty(IsPossibleDropTargetProperty);
        }

        TreeViewItem tvi = sender as TreeViewItem;
        if (tvi != null)
        {
            tvi.InvalidateProperty(IsPossibleDropTargetProperty);
        }
    }
}
EventManager.RegisterClassHandler(typeof(TreeViewItem),
             TreeViewItem.PreviewDropEvent,
             new DragEventHandler(OnDragDrop), true);