Skip to content

Commit

Permalink
Add drag drop reordering
Browse files Browse the repository at this point in the history
  • Loading branch information
SingletonSean committed Mar 25, 2021
1 parent 109a555 commit e73b9a5
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 21 deletions.
23 changes: 23 additions & 0 deletions DragDropDemo/Commands/TodoItemInsertedCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using DragDropDemo.ViewModels;
using MVVMEssentials.Commands;
using System;
using System.Collections.Generic;
using System.Text;

namespace DragDropDemo.Commands
{
public class TodoItemInsertedCommand : CommandBase
{
private readonly TodoItemListingViewModel _viewModel;

public TodoItemInsertedCommand(TodoItemListingViewModel viewModel)
{
_viewModel = viewModel;
}

public override void Execute(object parameter)
{
_viewModel.InsertTodoItem(_viewModel.InsertedTodoItemViewModel, _viewModel.TargetTodoItemViewModel);
}
}
}
46 changes: 46 additions & 0 deletions DragDropDemo/ViewModels/TodoItemListingViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,45 @@ public TodoItemViewModel RemovedTodoItemViewModel
}
}

private TodoItemViewModel _insertedTodoItemViewModel;
public TodoItemViewModel InsertedTodoItemViewModel
{
get
{
return _insertedTodoItemViewModel;
}
set
{
_insertedTodoItemViewModel = value;
OnPropertyChanged(nameof(InsertedTodoItemViewModel));
}
}

private TodoItemViewModel _targetTodoItemViewModel;
public TodoItemViewModel TargetTodoItemViewModel
{
get
{
return _targetTodoItemViewModel;
}
set
{
_targetTodoItemViewModel = value;
OnPropertyChanged(nameof(TargetTodoItemViewModel));
}
}

public ICommand TodoItemReceivedCommand { get; }
public ICommand TodoItemRemovedCommand { get; }
public ICommand TodoItemInsertedCommand { get; }

public TodoItemListingViewModel()
{
_todoItemViewModels = new ObservableCollection<TodoItemViewModel>();

TodoItemReceivedCommand = new TodoItemReceivedCommand(this);
TodoItemRemovedCommand = new TodoItemRemovedCommand(this);
TodoItemInsertedCommand = new TodoItemInsertedCommand(this);
}

public void AddTodoItem(TodoItemViewModel item)
Expand All @@ -61,6 +91,22 @@ public void AddTodoItem(TodoItemViewModel item)
}
}

public void InsertTodoItem(TodoItemViewModel insertedTodoItem, TodoItemViewModel targetTodoItem)
{
if(insertedTodoItem == targetTodoItem)
{
return;
}

int oldIndex = _todoItemViewModels.IndexOf(insertedTodoItem);
int nextIndex = _todoItemViewModels.IndexOf(targetTodoItem);

if(oldIndex != -1 && nextIndex != -1)
{
_todoItemViewModels.Move(oldIndex, nextIndex);
}
}

public void RemoveTodoItem(TodoItemViewModel item)
{
_todoItemViewModels.Remove(item);
Expand Down
6 changes: 3 additions & 3 deletions DragDropDemo/Views/TodoItemListingView.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@
mc:Ignorable="d">
<Grid>
<ListView
x:Name="lvItems"
AllowDrop="True"
DragLeave="TodoItemList_DragLeave"
Drop="TodoItemList_Drop"
DragOver="TodoItemList_DragOver"
ItemsSource="{Binding TodoItemViewModels}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="IsHitTestVisible" Value="{Binding IsTodoItemHitTestVisible, ElementName=root}" />

<EventSetter Event="MouseMove" Handler="TodoItem_MouseMove" />
<EventSetter Event="DragOver" Handler="TodoItem_DragOver" />
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
Expand Down
71 changes: 53 additions & 18 deletions DragDropDemo/Views/TodoItemListingView.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,6 @@ namespace DragDropDemo.Views
/// </summary>
public partial class TodoItemListingView : UserControl
{
public static readonly DependencyProperty IsTodoItemHitTestVisibleProperty =
DependencyProperty.Register("IsTodoItemHitTestVisible", typeof(bool), typeof(TodoItemListingView),
new PropertyMetadata(true));

public bool IsTodoItemHitTestVisible
{
get { return (bool)GetValue(IsTodoItemHitTestVisibleProperty); }
set { SetValue(IsTodoItemHitTestVisibleProperty, value); }
}

public static readonly DependencyProperty IncomingTodoItemProperty =
DependencyProperty.Register("IncomingTodoItem", typeof(object), typeof(TodoItemListingView),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
Expand Down Expand Up @@ -68,6 +58,36 @@ public ICommand TodoItemRemovedCommand
set { SetValue(TodoItemRemovedCommandProperty, value); }
}

public static readonly DependencyProperty TodoItemInsertedCommandProperty =
DependencyProperty.Register("TodoItemInsertedCommand", typeof(ICommand), typeof(TodoItemListingView),
new PropertyMetadata(null));

public ICommand TodoItemInsertedCommand
{
get { return (ICommand)GetValue(TodoItemInsertedCommandProperty); }
set { SetValue(TodoItemInsertedCommandProperty, value); }
}

public static readonly DependencyProperty InsertedTodoItemProperty =
DependencyProperty.Register("InsertedTodoItem", typeof(object), typeof(TodoItemListingView),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

public object InsertedTodoItem
{
get { return (object)GetValue(InsertedTodoItemProperty); }
set { SetValue(InsertedTodoItemProperty, value); }
}

public static readonly DependencyProperty TargetTodoItemProperty =
DependencyProperty.Register("TargetTodoItem", typeof(object), typeof(TodoItemListingView),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

public object TargetTodoItem
{
get { return (object)GetValue(TargetTodoItemProperty); }
set { SetValue(TargetTodoItemProperty, value); }
}

public TodoItemListingView()
{
InitializeComponent();
Expand All @@ -78,8 +98,6 @@ private void TodoItem_MouseMove(object sender, MouseEventArgs e)
if(e.LeftButton == MouseButtonState.Pressed &&
sender is FrameworkElement frameworkElement)
{
IsTodoItemHitTestVisible = false;

object todoItem = frameworkElement.DataContext;

DragDropEffects dragDropResult = DragDrop.DoDragDrop(frameworkElement,
Expand All @@ -90,12 +108,24 @@ private void TodoItem_MouseMove(object sender, MouseEventArgs e)
{
AddTodoItem(todoItem);
}
}
}

IsTodoItemHitTestVisible = true;
private void TodoItem_DragOver(object sender, DragEventArgs e)
{
if (TodoItemInsertedCommand?.CanExecute(null) ?? false)
{
if(sender is FrameworkElement element)
{
TargetTodoItem = element.DataContext;
InsertedTodoItem = e.Data.GetData(DataFormats.Serializable);

TodoItemInsertedCommand?.Execute(null);
}
}
}

private void TodoItemList_Drop(object sender, DragEventArgs e)
private void TodoItemList_DragOver(object sender, DragEventArgs e)
{
object todoItem = e.Data.GetData(DataFormats.Serializable);
AddTodoItem(todoItem);
Expand All @@ -112,11 +142,16 @@ private void AddTodoItem(object todoItem)

private void TodoItemList_DragLeave(object sender, DragEventArgs e)
{
if (TodoItemRemovedCommand?.CanExecute(null) ?? false)
HitTestResult result = VisualTreeHelper.HitTest(lvItems, e.GetPosition(lvItems));

if(result == null)
{
RemovedTodoItem = e.Data.GetData(DataFormats.Serializable);
TodoItemRemovedCommand?.Execute(null);
}
if (TodoItemRemovedCommand?.CanExecute(null) ?? false)
{
RemovedTodoItem = e.Data.GetData(DataFormats.Serializable);
TodoItemRemovedCommand?.Execute(null);
}
}
}
}
}
6 changes: 6 additions & 0 deletions DragDropDemo/Views/TodoView.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,11 @@
Margin="0 10 0 0"
DataContext="{Binding InProgressTodoItemListingViewModel}"
IncomingTodoItem="{Binding IncomingTodoItemViewModel}"
InsertedTodoItem="{Binding InsertedTodoItemViewModel}"
RemovedTodoItem="{Binding RemovedTodoItemViewModel}"
TargetTodoItem="{Binding TargetTodoItemViewModel}"
TodoItemDropCommand="{Binding TodoItemReceivedCommand}"
TodoItemInsertedCommand="{Binding TodoItemInsertedCommand}"
TodoItemRemovedCommand="{Binding TodoItemRemovedCommand}" />
</Grid>

Expand All @@ -51,8 +54,11 @@
Margin="0 10 0 0"
DataContext="{Binding CompletedTodoItemListingViewModel}"
IncomingTodoItem="{Binding IncomingTodoItemViewModel}"
InsertedTodoItem="{Binding InsertedTodoItemViewModel}"
RemovedTodoItem="{Binding RemovedTodoItemViewModel}"
TargetTodoItem="{Binding TargetTodoItemViewModel}"
TodoItemDropCommand="{Binding TodoItemReceivedCommand}"
TodoItemInsertedCommand="{Binding TodoItemInsertedCommand}"
TodoItemRemovedCommand="{Binding TodoItemRemovedCommand}" />
</Grid>
</Grid>
Expand Down

0 comments on commit e73b9a5

Please sign in to comment.