Drag and Drop na DataGrid wpf mvvm

0

Cześć czy jest możliwość napisania kodu który umożliwia za pomocą myszki zmieniać pozycję wierszy na Data gridzie na wzorcu mvvm ? :)

ViewModel:

    public class MainWindowViewModel : ViewModelBase
    {
        public MainWindowViewModel()
        {
            GenerateReportCommand = new ClickCommand();
            GenerateReportCommand.Enabled = true;
            GenerateReportCommand.OnClick += OnGenerateReport;

            Users = new ObservableCollection<User>();

            Users.Add(new User("Jan", "Nowak"));
            Users.Add(new User("Miłosz", "Iles"));
            Users.Add(new User("Anna", "Fatyga"));
            MySource = CollectionViewSource.GetDefaultView(Users);
        }

        private void OnGenerateReport()
        {
            MySource.Refresh();

            var s = MySource.OfType<User>();
            var users = Users;
        }

        public ClickCommand GenerateReportCommand { get; set; }


        private ObservableCollection<User> _user;

        public ObservableCollection<User> Users
        {
            get => _user;
            set
            {
                _user = value;
                OnPropertyChanged(nameof(Users));
            }
        }

        public ICollectionView MySource { get; set; }
    }

XAML:

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
        xmlns:dd="urn:gong-wpf-dragdrop"
        
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <DataGrid Grid.Row="0" Grid.Column="0" ItemsSource="{Binding MySource}" IsReadOnly="True" AutoGenerateColumns="False" AllowDrop="True"
                                  CanUserAddRows="False"
                                  CanUserDeleteRows="False"
                                  dd:DragDrop.DropScrollingMode="HorizontalOnly"
                  dd:DragDrop.IsDragSource="True"
                  dd:DragDrop.IsDropTarget="True">
            <DataGrid.Columns>
                <DataGridTextColumn SortMemberPath="UserFirstName" Header="First Name" IsReadOnly="False" CanUserSort="true"  Binding="{Binding UserFirstName}">
                    <DataGridTextColumn.ElementStyle>
                        <Style>
                            <Setter Property="TextBlock.TextWrapping" Value="Wrap" />
                            <Setter Property="TextBlock.TextAlignment" Value="Center" />
                        </Style>
                    </DataGridTextColumn.ElementStyle>
                </DataGridTextColumn>
                <DataGridTextColumn SortMemberPath="UserLastName" Header="Last Name" IsReadOnly="False" CanUserSort="true" Binding="{Binding UserLastName}" >
                    <DataGridTextColumn.ElementStyle>
                        <Style>
                            <Setter Property="TextBlock.TextWrapping" Value="Wrap" />
                            <Setter Property="TextBlock.TextAlignment" Value="Center" />
                        </Style>
                    </DataGridTextColumn.ElementStyle>
                </DataGridTextColumn>
            </DataGrid.Columns>

        </DataGrid>

        <Button Width="20" Height="20" Content="Generate" Command="{Binding Path=GenerateReportCommand}"></Button>
    </Grid>
</Window>

0

@mariano901229: W tym przykładzie jak i w moim innym projekcie, mam problem z tym że gdy posortuje sobie kolumnę np : ProducId to drag and drop przestaje działać :/

0

Zrobiłem na szybko, może się przyda a może nie:
MainWindow.xaml.cs

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            ViewModel.Elements.Add(new Element() { lp = 1, Name = "Jeden" });
            ViewModel.Elements.Add(new Element() { lp = 2, Name = "Dwa" });
            ViewModel.Elements.Add(new Element() { lp = 3, Name = "Trzy" });
            ViewModel.Elements.Add(new Element() { lp = 4, Name = "Cztery" });
            ViewModel.Elements.Add(new Element() { lp = 5, Name = "Pięć" });
        }

        private void DataGrid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Dispatcher?.Invoke(() =>
            {
                ViewModel.IsMoving = true;
                ViewModel.CanSetSelectedElementWhenLeftMouseButtonDown = true;
            });
        }
        private void DataGrid_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            Dispatcher?.Invoke(() =>
            {
                ViewModel.IsMoving = false;
                if(ViewModel.SelectedElementWhenLeftMouseButtonDown != null 
                    && ViewModel.SelectedElement != null 
                    && ViewModel.SelectedElement != ViewModel.SelectedElementWhenLeftMouseButtonDown)
                {
                    int DestinationIndex = ViewModel.Elements.IndexOf(ViewModel.SelectedElement);
                    int SourceIndex = ViewModel.Elements.IndexOf(ViewModel.SelectedElementWhenLeftMouseButtonDown);
                    ViewModel.Elements.Move(SourceIndex, DestinationIndex);
                    MessageBox.Show("Moving from " + SourceIndex.ToString() + " to " + DestinationIndex.ToString());
                }
            });
        }
      
        private void DataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            Dispatcher?.Invoke(() =>
            {
                if(ViewModel.CanSetSelectedElementWhenLeftMouseButtonDown)
                {
                    ViewModel.SelectedElementWhenLeftMouseButtonDown = ViewModel.SelectedElement;
                    ViewModel.CanSetSelectedElementWhenLeftMouseButtonDown = false;
                } 
            });
        }
    }

MainWindow.xaml

<Window x:Class="WPFApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WPFApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.DataContext>
            <local:MainWindowViewModel x:Name="ViewModel"/>
        </Grid.DataContext>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="25"/>
        </Grid.RowDefinitions>
        <DataGrid 
            ItemsSource="{Binding Path=Elements}" 
            SelectionMode="Single" 
            SelectedItem="{Binding Path=SelectedElement, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
            PreviewMouseLeftButtonDown="DataGrid_PreviewMouseLeftButtonDown"
            PreviewMouseLeftButtonUp="DataGrid_PreviewMouseLeftButtonUp"
            SelectionChanged="DataGrid_SelectionChanged">
            
        </DataGrid>
        <WrapPanel Grid.Row="1">
            <TextBlock Text="{Binding Path=IsMoving}" Grid.Row="1"/>
            <TextBlock Text=" / Selected: "/>
            <TextBlock Text="{Binding Path=SelectedElement.Name}"/>
            <TextBlock Text=" / SelectedMouseDown: "/>
            <TextBlock Text="{Binding Path=SelectedElementWhenLeftMouseButtonDown.Name}"/>
        </WrapPanel>
        
    </Grid>
</Window>

mainWindowViewModel.cs

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace WPFApp
{
    public class MainWindowViewModel : INotifyPropertyChanged
    {
        public ObservableCollection<Element> Elements { get; private set; } = new ObservableCollection<Element>();

        private Element selectedElementWhenLeftMouseButtonDown = null;
        public Element SelectedElementWhenLeftMouseButtonDown
        {
            get { return selectedElementWhenLeftMouseButtonDown; }
            set { selectedElementWhenLeftMouseButtonDown = value; OnPropertyChanged("SelectedElementWhenLeftMouseButtonDown"); }
        }

        private Element selectedElement = null;
        public Element SelectedElement
        {
            get { return selectedElement; }
            set { selectedElement = value; OnPropertyChanged("SelectedElement"); }
        }
        private bool isMoving = false;
        public bool IsMoving
        {
            get { return isMoving; }
            set { isMoving = value; OnPropertyChanged("IsMoving"); }
        }
        private bool canSetSelectedElementWhenLeftMouseButtonDown = false;
        public bool CanSetSelectedElementWhenLeftMouseButtonDown
        {
            get { return canSetSelectedElementWhenLeftMouseButtonDown; }
            set { canSetSelectedElementWhenLeftMouseButtonDown = value; OnPropertyChanged("CanSetSelectedElementWhenLeftMouseButtonDown"); }
        }




        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] String propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    public class Element
    {
        public int lp { get; set; }
        public string Name { get; set; }
    }
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1