philkark
philkark

Reputation: 2457

Drag item from Listbox and start method on drop into specific Canvas

I am quite new to C# so please keep things as simple as possible. My problem is as follows: I have a Listbox to which I add Items dynamically at runtime and I also have four different Canvases within my UI. Now the user has to be able to drag any Item from the Listbox and drop it into one of the four Canvases. Upon drop a method will be started which needs to know which Item has been draged and into which Canvas it was dropped.

I have not implemented anything yet but here at least my XAML:

<Grid Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="gridMenu" VerticalAlignment="Stretch" Width="Auto" Background="#FFE6E6E6">
     <ListBox Grid.Row="2" Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="listBox1" VerticalAlignment="Stretch" Width="Auto" Background="#FFE6E6E6" BorderBrush="{x:Null}" Panel.ZIndex="1" PreviewMouseDown="listBox1_PreviewMouseLeftButtonDown">
        <ListBoxItem Content="test1" />
        <ListBoxItem Content="test2" />
        <ListBoxItem Content="test3" />
        <ListBoxItem Content="test4" />
        <ListBoxItem Content="test5" />
    </ListBox>
</Grid>
<Grid Grid.Column="1" Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="gridImage" VerticalAlignment="Stretch" Width="Auto" TextBlock.Drop="grid1_Drop">
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
        <Canvas Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="canvasImage1" VerticalAlignment="Stretch" Width="Auto" />
        <Canvas Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="canvasImage2" VerticalAlignment="Stretch" Width="Auto" Grid.Column="1" />
        <Canvas Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="canvasImage3" VerticalAlignment="Stretch" Width="Auto" Grid.Row="1" />
        <Canvas Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="canvasImage4" VerticalAlignment="Stretch" Width="Auto" Grid.Column="1" Grid.Row="1" />
</Grid>

Upvotes: 4

Views: 2505

Answers (2)

SvenG
SvenG

Reputation: 5195

I think Drag and Drop isn't an easy topic, so I am afraid I can't make it that simple and I agree with ekholm: You will definitely need a decent c#/wpf knowledge to succesfully implement this. Even when you get your code to run you will be stuck when you want to modify/extend your DragDrop Code.

Here's an example to get you started based on your provided markup:

XAML:

    <Grid Grid.Row="1" Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="gridImage" VerticalAlignment="Stretch" Width="Auto">
      <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
      </Grid.RowDefinitions>
      <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
      </Grid.ColumnDefinitions>

      <Canvas Background="LightGreen" AllowDrop="True" Drop="canvasImage_Drop" DragEnter="canvasImage_DragEnter" Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="canvasImage1" VerticalAlignment="Stretch" Width="Auto" />

      <Canvas Background="LightYellow" AllowDrop="True" Drop="canvasImage_Drop" DragEnter="canvasImage_DragEnter"  Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="canvasImage2" VerticalAlignment="Stretch" Width="Auto" Grid.Column="1" />

      <Canvas Background="LightPink" AllowDrop="True" Drop="canvasImage_Drop" DragEnter="canvasImage_DragEnter"  Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="canvasImage3" VerticalAlignment="Stretch" Width="Auto" Grid.Row="1" />

      <Canvas Background="LightSteelBlue" AllowDrop="True" Drop="canvasImage_Drop" DragEnter="canvasImage_DragEnter"  Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="canvasImage4" VerticalAlignment="Stretch" Width="Auto" Grid.Column="1" Grid.Row="1" />
    </Grid>
  </Grid>

Code behind:

private Point _startPoint;
private static readonly string _dropIdentifier = "dropIdentifier";

private void listBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
  // The initial mouse position
  _startPoint = e.GetPosition(null);
}

private void listBox_PreviewMouseMove(object sender, MouseEventArgs e)
{
  // Get the current mouse position
  Point mousePos = e.GetPosition(null);
  Vector diff = _startPoint - mousePos;

  if (e.LeftButton == MouseButtonState.Pressed &&
      (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
      Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance))
  {
    // Get the dragged ListBoxItem
    var listBox = sender as ListBox;
    var listBoxItem = listBox.SelectedItem;

    // Initialize the drag & drop operation
    DataObject dragData = new DataObject(_dropIdentifier, listBoxItem);
    DragDrop.DoDragDrop(listBox, dragData, DragDropEffects.Move);
  } 
}

private void canvasImage_Drop(object sender, DragEventArgs e)
{
  if (e.Data.GetDataPresent(_dropIdentifier))
  {
    var item = e.Data.GetData(_dropIdentifier) as ListBoxItem;
    DropOnCanvas(sender as Canvas, item);
  }
}

private void canvasImage_DragEnter(object sender, DragEventArgs e)
{
  if (!e.Data.GetDataPresent(_dropIdentifier) ||
    sender == e.Source)
  {
    e.Effects = DragDropEffects.None;
  }
}

public void DropOnCanvas(Canvas targetCanvas, ListBoxItem item)
{
  // do your stuff here ...
  int textHeight = 20;
  var text = new TextBlock() { Text = item.Content.ToString(), Height = textHeight };
  Canvas.SetTop(text, targetCanvas.Children.Count * textHeight);
  targetCanvas.Children.Add(text);
}

Upvotes: 3

ekholm
ekholm

Reputation: 2573

This tutorial should get you started: http://wpftutorial.net/DragAndDrop.html

Upvotes: 2

Related Questions