diff --git a/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs b/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs index a01cda93..401657fd 100644 --- a/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs +++ b/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs @@ -1064,6 +1064,17 @@ namespace v2rayN.ViewModels } } + public void MoveServerTo(int startIndex, ProfileItemModel targetItem) + { + var targetIndex = _profileItems.IndexOf(targetItem); + if (startIndex >= 0 && targetIndex >= 0 && startIndex != targetIndex) + { + if (ConfigHandler.MoveServer(ref _config, ref _lstProfile, startIndex, EMove.Position, targetIndex) == 0) + { + RefreshServers(); + } + } + } public void ServerSpeedtest(ESpeedActionType actionType) { diff --git a/v2rayN/v2rayN/Views/MainWindow.xaml b/v2rayN/v2rayN/Views/MainWindow.xaml index a198b5c3..83c15995 100644 --- a/v2rayN/v2rayN/Views/MainWindow.xaml +++ b/v2rayN/v2rayN/Views/MainWindow.xaml @@ -350,11 +350,12 @@ - + ViewModel, typeof(MainWindowViewModel)); @@ -171,8 +177,7 @@ namespace v2rayN.Views var IsAdministrator = Utils.IsAdministrator(); this.Title = $"{Utils.GetVersion()} - {(IsAdministrator ? ResUI.RunAsAdmin : ResUI.NotRunAsAdmin)}"; - togEnableTun.Visibility = IsAdministrator ? Visibility.Visible : Visibility.Hidden; - txtEnableTun.Visibility = IsAdministrator ? Visibility.Visible : Visibility.Hidden; + spEnableTun.Visibility = IsAdministrator ? Visibility.Visible : Visibility.Collapsed; } #region Event @@ -438,6 +443,100 @@ namespace v2rayN.Views #endregion + #region Drag and Drop + + private Point startPoint = new Point(); + private int startIndex = -1; + private string formatData = "ProfileItemModel"; + + /// + /// Helper to search up the VisualTree + /// + /// + /// + /// + private static T? FindAnchestor(DependencyObject current) where T : DependencyObject + { + do + { + if (current is T) + { + return (T)current; + } + current = VisualTreeHelper.GetParent(current); + } + while (current != null); + return null; + } + + + private void LstProfiles_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) + { + // Get current mouse position + startPoint = e.GetPosition(null); + } + private void LstProfiles_MouseMove(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 Item + var listView = sender as DataGrid; + if (listView == null) return; + var listViewItem = FindAnchestor((DependencyObject)e.OriginalSource); + if (listViewItem == null) return; // Abort + // Find the data behind the ListViewItem + ProfileItemModel item = (ProfileItemModel)listView.ItemContainerGenerator.ItemFromContainer(listViewItem); + if (item == null) return; // Abort + // Initialize the drag & drop operation + startIndex = lstProfiles.SelectedIndex; + DataObject dragData = new DataObject(formatData, item); + DragDrop.DoDragDrop(listViewItem, dragData, DragDropEffects.Copy | DragDropEffects.Move); + } + } + + private void LstProfiles_DragEnter(object sender, DragEventArgs e) + { + if (!e.Data.GetDataPresent(formatData) || sender != e.Source) + { + e.Effects = DragDropEffects.None; + } + } + + private void LstProfiles_Drop(object sender, DragEventArgs e) + { + if (e.Data.GetDataPresent(formatData) && sender == e.Source) + { + // Get the drop Item destination + var listView = sender as DataGrid; + if (listView == null) return; + var listViewItem = FindAnchestor((DependencyObject)e.OriginalSource); + if (listViewItem == null) + { + // Abort + e.Effects = DragDropEffects.None; + return; + } + // Find the data behind the Item + ProfileItemModel item = (ProfileItemModel)listView.ItemContainerGenerator.ItemFromContainer(listViewItem); + if (item == null) return; + // Move item into observable collection + // (this will be automatically reflected to lstView.ItemsSource) + e.Effects = DragDropEffects.Move; + + ViewModel?.MoveServerTo(startIndex, item); + + startIndex = -1; + } + } + + #endregion + } }