Aquí podría ser tu PUBLICIDAD


Resalte que se arrastra el elemento TreeView

votos
5

En mi aplicación, tengo una TreeView que permite arrastrar / soltar. Tengo toda la funcionalidad funcionando bien, sin embargo, tengo dificultades para resaltar un TreeViewItem cuando se arrastra. Este es mi estilo para mi artículo treeview. El desencadenador IsMouseOver no funciona mientras se arrastra, porque el arrastre parece bloquear otros eventos del mouse. ¿Alguien puede ayudarme a activar los mismos cambios de borde en mi elemento treeview mientras arrastro?

<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>
Publicado el 12/03/2009 a las 19:25
fuente por usuario uncle hammy
En otros idiomas...        العربية       

4 respuestas

votos
17

Estoy usando una propiedad adjunta para esto, y luego uso esa propiedad en mi archivo xaml para cambiar el color de fondo del elemento de vista en árbol:

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
    }
}

y luego en el archivo xaml:

    <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>
Respondida el 12/03/2009 a las 08:45
fuente por usuario Stefan


Aquí podría ser tu PUBLICIDAD


votos
4

Mire el evento DragOver (y posiblemente DragEnter / DragLeave) en lugar de IsMouseOver.

Respondida el 12/03/2009 a las 07:29
fuente por usuario Bob King

votos
1

Además de la respuesta de Stefan, he encontrado que es necesario añadir también el evento Drop:

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

y el registro de evento de colocación también:

EventManager.RegisterClassHandler(typeof(TreeViewItem),
             TreeViewItem.PreviewDropEvent,
             new DragEventHandler(OnDragDrop), true);

De lo contrario, si se produce caída de uno sobre otro treeitem, el fondo podría no cambiar. Lo mismo si se pulsa la tecla ESC.

Respondida el 20/09/2013 a las 03:38
fuente por usuario XMight

votos
1

Este post es simplemente una portabilidad de respuesta impresionante de Stefan arriba para VB, para los que trabajamos en esos confines; No tengo nada que ofrecer excepto la esperanza de que no la pata nada demasiado mal. Parece que funciona para mí:

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

Espacio de nombres fin

Respondida el 08/05/2012 a las 10:20
fuente por usuario dansan