Search code examples
wpfrouted-events

EventTriggers in ListViewItem should not get triggered by contained ItemTemplate


In an wpf application I have a ListView with Drag and Drop functionality, which inserts the dropped element at the position, where it was dropped instead of the end of the list. Thats working fine. What i now want to achieve seemed to be the simple part :) I want to make clear for the user at which position in the list the currently dragged element will be dropped. There should be a gap where the new element will be inserted.

My approach was to change the Padding of the ListViewItem at the current mousePosition.

<ControlTemplate TargetType="ListViewItem">
    <Border x:Name="BorderA">
        <ContentPresenter />
        <Border.Triggers>

            <!--padding for gap when mouse hovers element-->
            <EventTrigger RoutedEvent="DragEnter" SourceName="BorderA">
                <BeginStoryboard>
                    <Storyboard>
                        <ThicknessAnimation
                            Storyboard.TargetProperty="Padding"
                            From="0,0,0,0" To="0,25,0,0" 
                            BeginTime="0:0:0" Duration="0:0:0.5" 
                            AutoReverse="False" />
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>

            <!--back to normal padding-->
            <EventTrigger RoutedEvent="DragLeave" SourceName="BorderA">
                <BeginStoryboard>
                    <Storyboard>
                        <ThicknessAnimation
                            Storyboard.TargetProperty="Padding"
                            From="0,25,0,0" To="0,0,0,0" 
                            BeginTime="0:0:0" Duration="0:0:0.5" 
                            AutoReverse="False" />
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>

        </Border.Triggers>
    </Border>
</ControlTemplate>

I also need a DataTemplate to display my listItems correctly. I simplified that here, which might make it appear nearly redundand, but in reality i need to display a complex viewModel and it seems to be part of the problem.

<DataTemplate x:Key="SortableListBoxItemTemplate" DataType="item:SortableListItemViewModel">
    <Border Background="{StaticResource CallToActionBrush}"
            BorderThickness="{StaticResource BorderThickness}"
            BorderBrush="{StaticResource PassiveBorderBrush_Strong}">
    </Border>
</DataTemplate>

That seemd to work. When i hover an element while dragging another, a gap between that element and the previous list element appears. But sometimes when the gap grows the mouse position will be within this gap. That triggeres the DragLeave Event, the gap starts closing until the listItem has reached the mouse position again and so on. That causes an ugly flickering and i am not sure how to avoid that. Everything is fine as long as the DataTemplate hasn't a Background color. But thats not the visual effect i want. Is there a way to trigger that DragEnter and DragLeave events only if they were fired from my listviewItem (or BorderA)? Or is there a complete other way to achieve the effect i want?


Solution

  • I found a solution. The problem wasn't the DragLeave event, but the DragEnter event when the cursor enters the Item (coming from the gap). This triggers the animation to start again and someone stupid has told this animation to start From="0,0,0,0"... I removed that part and everything worked just fine.

    For me there is still a question. Maybe in some cases removing the From-part is not an option. Is there a way to add a condition to the event trigger. Something like a Multitrigger?