ubergeek ubergeek - 22 days ago 11
Vb.net Question

Drag and Drop rows of Datagrid WPF Code convertion from C# to VB.NET

So I have been trying to implement Drag and Drop functionality for WPF datagrid in vb.net . I have found this tutorial which is doing the same. the only problem for me is - the tutorial and code is in C#.

C# Code :

namespace WPF40_DataGrid_Row_Drag_Drop
{

// Declare a Delegate which will return the position of the
// DragDropEventArgs and the MouseButtonEventArgs event object
public delegate Point GetDragDropPosition(IInputElement theElement);

public partial class MainWindow : Window
{
int prevRowIndex = -1;
public MainWindow()
{
InitializeComponent();
//The Event on DataGrid for selecting the Row
this.dgEmployee.PreviewMouseLeftButtonDown +=
new MouseButtonEventHandler(dgEmployee_PreviewMouseLeftButtonDown);
//The Drop Event
this.dgEmployee.Drop += new DragEventHandler(dgEmployee_Drop);
}

void dgEmployee_Drop(object sender, DragEventArgs e)
{
if (prevRowIndex < 0)
return;

int index = this.GetDataGridItemCurrentRowIndex(e.GetPosition);

//The current Rowindex is -1 (No selected)
if (index < 0)
return;
//If Drag-Drop Location are same
if (index == prevRowIndex)
return;
//If the Drop Index is the last Row of DataGrid(
// Note: This Row is typically used for performing Insert operation)
if (index == dgEmployee.Items.Count-1)
{
MessageBox.Show("This row-index cannot be used for Drop Operations");
return;
}

EmployeeCollection myEmps = Resources["EmpDs"] as EmployeeCollection;

Employee movedEmps = myEmps[prevRowIndex];
myEmps.RemoveAt(prevRowIndex);

myEmps.Insert(index, movedEmps);
}

void dgEmployee_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
prevRowIndex = GetDataGridItemCurrentRowIndex(e.GetPosition);

if (prevRowIndex < 0)
return;
dgEmployee.SelectedIndex = prevRowIndex;

Employee selectedEmp = dgEmployee.Items[prevRowIndex] as Employee;

if (selectedEmp == null)
return;

//Now Create a Drag Rectangle with Mouse Drag-Effect
//Here you can select the Effect as per your choice

DragDropEffects dragdropeffects = DragDropEffects.Move;

if (DragDrop.DoDragDrop(dgEmployee, selectedEmp, dragdropeffects)
!= DragDropEffects.None)
{
//Now This Item will be dropped at new location and so the new Selected Item
dgEmployee.SelectedItem = selectedEmp;
}
}

private bool IsTheMouseOnTargetRow(Visual theTarget, GetDragDropPosition pos)
{
Rect posBounds = VisualTreeHelper.GetDescendantBounds(theTarget);
Point theMousePos = pos((IInputElement)theTarget);
return posBounds.Contains(theMousePos);
}

private DataGridRow GetDataGridRowItem(int index)
{
if (dgEmployee.ItemContainerGenerator.Status
!= GeneratorStatus.ContainersGenerated)
return null;

return dgEmployee.ItemContainerGenerator.ContainerFromIndex(index)
as DataGridRow;
}

private int GetDataGridItemCurrentRowIndex(GetDragDropPosition pos)
{
int curIndex = -1;
for (int i = 0; i < dgEmployee.Items.Count; i++)
{
DataGridRow itm = GetDataGridRowItem(i);
if (IsTheMouseOnTargetRow(itm, pos))
{
curIndex = i;
break;
}
}
return curIndex;
}
}
}


VB Code:

Public Delegate Function GetDragDropPosition(ByRef element As IInputElement) As Point

public partial class MainWindow : Window

Dim prevRowIndex As Integer = -1
public Sub MainWindow()

InitializeComponent()
AddHandler datagridRoll.PreviewMouseLeftButtonDown, AddressOf datagridRoll_PreviewMouseLeftButtonDown
AddHandler datagridRoll.Drop, AddressOf datagridRoll_Drop
End Sub

Private Sub datagridRoll_Drop(sender As Object, e As System.Windows.DragEventArgs)
If prevRowIndex < 0 Then
Return
End If


Dim index As Integer = GetDataGridItemCurrentRowIndex(e.GetPosition(datagridRoll))
If (index < 0) Then
Return
End If


If (index = prevRowIndex) Then
Return
End If

If (index = datagridRoll.Items.Count - 1) Then

MessageBox.Show("This row-index cannot be used for Drop Operations")
Return

End If

End Sub

Private Sub datagridRoll_PreviewMouseLeftButtonDown(sender As Object, e As MouseButtonEventArgs)
prevRowIndex = GetDataGridItemCurrentRowIndex(e.GetPosition(datagridRoll))
prevRowIndex = datagridRoll.SelectedIndex
If (prevRowIndex < 0) Then
Return
End If
datagridRoll.SelectedIndex = prevRowIndex

Dim selectedEmp As DataGridRow = TryCast(datagridRoll.ItemContainerGenerator.ContainerFromIndex(prevRowIndex), DataGridRow)

If (selectedEmp Is Nothing) Then
Return
End If

Dim DragDropEffects As DragDropEffects = DragDropEffects.Move

If (DragDrop.DoDragDrop(datagridRoll, selectedEmp, DragDropEffects) <> DragDropEffects.None) Then

datagridRoll.SelectedItem = selectedEmp

End If
End Sub

Public Function IsTheMouseOnTargetRow(theTarget As Visual, pos As GetDragDropPosition) As Boolean
Dim posBounds As Rect = VisualTreeHelper.GetDescendantBounds(theTarget)
posBounds = VisualTreeHelper.GetContentBounds(theTarget)


Dim theMousePos As Point = pos(DirectCast(theTarget, IInputElement))
Return posBounds.Contains(theMousePos )
End Function

Public Function GetDataGridRowItem(index As Integer) As DataGridRow
If datagridRoll.ItemContainerGenerator.Status <> GeneratorStatus.ContainersGenerated Then
Return Nothing
End If

Return TryCast(datagridRoll.ItemContainerGenerator.ContainerFromIndex(index), DataGridRow)

End Function
Public Function GetDataGridItemCurrentRowIndex(pos As Point) As Integer
Dim curIndex As Integer = -1
For i As Integer = 0 To datagridRoll.Items.Count - 1 - 26
Dim itm As DataGridRow = GetDataGridRowItem(i)
If IsTheMouseOnTargetRow(itm, pos) Then
curIndex = i
Exit For
End If
Next
Return curIndex
End Function
End Class


Now, at Line
prevRowIndex = GetDataGridItemCurrentRowIndex(e.GetPosition(datagridRoll))
I am getting an error like ->
Error Value of type 'System.Windows.Point' cannot be converted to 'MyappWPF.GetDragDropPosition'.
I guess it has something to do with Type of delegate GetDragDropPosition.
I am not able to figure out what is wrong.

Answer

There are a few mistakes in the conversion:

  1. You are making the delegate parameter 'ByRef' for no apparent reason - it should be:

    Public Delegate Function GetDragDropPosition(ByVal theElement As IInputElement) As Point

  2. You are not specifying the base class correctly - it should be:

    Partial Public Class MainWindow
    Inherits Window

  3. Your 'For' loop is subtracting 26 - again for no apparent reason - it should be:

    For i As Integer = 0 To dgEmployee.Items.Count - 1

Comments