Search code examples
c#wpfwindowsuser-interface

How do I build a WPF application where I can drag and drop a user control between windows?


I'm building a simple Todo List application where I want to be able to have multiple lists floating around my desktop that I can label and manage tasks in.

The relevant UIElements in my app are:

Window1 (Window) TodoList (User Control) TodoStackCard (User Control)

Window1 looks like this:

<Window x:Class="TaskHole.App.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:t="clr-namespace:TaskHole.App.Controls"
    xmlns:tcc="clr-namespace:TaskHole.CustomControls"
    Title="Window1" Width="500" Height="500" Background="Transparent" WindowStyle="None" AllowsTransparency="True" >
    <Canvas Name="maincanvas" Width="500" Height="500" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
        <ResizeGrip SizeChanged="ResizeGrip_SizeChanged" />
        <t:TodoList Canvas.Top="0" Canvas.Left="0" MinWidth="30" Width="50" Height="500" x:Name="todoList" TaskHover="todoList_TaskHover" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
    </Canvas>
</Window>

TodoList looks like this:

<UserControl x:Class="TaskHole.App.Controls.TodoList"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:t="clr-namespace:TaskHole.App.Controls"
        xmlns:tcc="clr-namespace:TaskHole.CustomControls"
        Background="Transparent">
    <StackPanel VerticalAlignment="Bottom" HorizontalAlignment="Stretch" MinWidth="1" Grid.Row="2" Height="Auto" AllowDrop="True">
        <ItemsControl Name="todolist" ItemsSource="{Binding}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <VirtualizingStackPanel Name="stackPanel" VerticalAlignment="Bottom">
                    </VirtualizingStackPanel>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <t:TodoStackCard x:Name="card" TaskHover="card_TaskHover" Orientation="Vertical" VerticalContentAlignment="Top" />
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </StackPanel>
</UserControl>

I have multiple instances of these windows, and I want to be able to drag any of the controls between the windows. I have tried using a Thumb control and, while this works, it only allows me to drag a control around the containing canvas.

How do I mimic the behaviour of, say, Windows Explorer, where I can drag a file outside of the application and onto another application, all the while seeing a ghosted representation of the file under the cursor.

Can I accomplish this purely in C# and WPF? If so/if not, how?


Solution

  • You have to call DoDragDrop to initialize the Drag And Drop framework. Jaime Rodriguez provides a guide to Drag and Drop here