Shankar Raju
Shankar Raju

Reputation: 4546

ListBox removes elements when dragged out of the control

I am using the listbox to drag drop elements within the control so that the users can order them. I was able to achieve it, however the problem is, I do not want the users to drag and drop elements outside the listbox. Currently, if you do it, it is removing the element from the listbox items.

This is my code:

    <telerik:RadListBox x:Name="SequenceListBox" x:FieldModifier="public"
                        DockPanel.Dock="Bottom" AllowDrop="True"
                        HorizontalAlignment="Stretch"
                        VerticalAlignment="Stretch"
                        ScrollViewer.VerticalScrollBarVisibility="Hidden"
                        ScrollViewer.HorizontalScrollBarVisibility="Auto"
                        Background="Transparent" Margin="30,5,30,5"
                        ItemTemplate="{DynamicResource ListBoxItemTemplate}">
        <telerik:RadListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Horizontal" VerticalAlignment="Center"/>
            </ItemsPanelTemplate>
        </telerik:RadListBox.ItemsPanel>
        <telerik:RadListBox.DragVisualProvider>
            <telerik:ScreenshotDragVisualProvider />
        </telerik:RadListBox.DragVisualProvider>
        <telerik:RadListBox.DragDropBehavior>
            <telerik:ListBoxDragDropBehavior AllowReorder="True" />
        </telerik:RadListBox.DragDropBehavior>
    </telerik:RadListBox>

        <!-- Sequence ListBox style start -->
    <DataTemplate x:Key="ListBoxItemTemplate">
        <DataTemplate.Triggers>
            <Trigger Property="IsMouseOver" Value="true">
                <Setter Property="LayoutTransform">
                    <Setter.Value>
                        <ScaleTransform ScaleX="1.5" />
                    </Setter.Value>
                </Setter>
            </Trigger>
        </DataTemplate.Triggers>
        <!--<Border BorderThickness="1" BorderBrush="Wheat">-->
        <TextBlock Text="{Binding Path=AttributeName}" MinWidth="30" Foreground="Black"
                   FontSize="12" FontFamily="Segoe UI" ToolTip="Drag and Drop to re-arrange"
                   VerticalAlignment="Center" HorizontalAlignment="Center" />
        <!--</Border>-->
    </DataTemplate>

My question is similar to: this, but I am still not clear on how to implement it. Please help me with a solution.

Also, I would like to highlight (with some color) the border between 2 elements when the user is trying to drop it, but I am not sure about how to implement this.

How do I modify my code so the listbox will not remove items when they are dropped outside of the control?

Upvotes: 0

Views: 1767

Answers (1)

Bill Tarbell
Bill Tarbell

Reputation: 5234

I haven't done this myself, but you could look at DragDrop.PreviewDragLeave. This event is fired right when the mouse is dragging the element out of the bounds of a control.

Once you determine you need to cancel the drag then you'll need to set some class-level variable that you can read in DragDrop.QueryContinueHandler. Sadly, you can't cancel the drag while you're in PreviewDragLeave because the eventArgs doesn't support it.

bool shouldICancelDrag = false

void listBox1_PreviewDragLeave(object sender, DragEventArgs e)
{
   shouldICancelDrag = true; 
}

private void OnQueryContinueDrag(object sender, QueryContinueDragEventArgs e)
{
   if(shouldICancelDrag)
   {
       e.Action = DragAction.Cancel;
       e.Handled = true;
       shouldICancelDrag = false;
   }
}

EDIT: Here's an alternative for the case where you want to allow them to drag outside of the listbox but not allow them to drop the item outside (meaning they have to return the item to the listbox or the drag event will be cancelled).

bool shouldICancelDrag = false

//changed this to be previewDrop on the Window (not the listbox)
void window1_PreviewDrop(object sender, DragEventArgs e)
{
   //check if the item was dropped on something other than the listbox
   //you may need to toy with using e.Source instead (break and see what you're getting via the debugger)
   if (! (e.OriginalSource is ListBox))
     shouldICancelDrag = true; 
}

private void OnQueryContinueDrag(object sender, QueryContinueDragEventArgs e)
{
   if(shouldICancelDrag)
   {
       e.Action = DragAction.Cancel;
       e.Handled = true;
       shouldICancelDrag = false;
   }
}

Upvotes: 1

Related Questions