cobek Ответов: 0

Проблема с DataGrid отмену строку, удалив первую строку


Привет, проблема у меня следующая: когда первые две строки в DataGrid выбраны и первая строка удалена, выбранная строка ниже становится первой строкой и отменяется. Если я сортирую любой из столбцов,выбор этой строки возвращается. Если я закрою окно, то получу информацию о том, что отмененная строка действительно выбрана (запрос содержимого базового связанного свойства SelectedUsers в UsersViewModel). Есть ли кто-нибудь, кто может помочь или объяснить мне, если я сделал что-то не так или это может быть ошибка? Я предоставил полный исходный код ниже. Спасибо за помощь.

Файл MainWindow.язык XAML:
Window x:Class="DeleteFirstRowIssue.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:DeleteFirstRowIssue"
        Title="MainWindow" Height="350" Width="400">
    <Window.Resources>
        <Style x:Key="CustomDataGridCellStyle" TargetType="{x:Type DataGridCell}">
                <Style.Triggers>
                    <Trigger Property="IsSelected" Value="True">
                        <Setter Property="Background" Value="Red"/>
                        <Setter Property="FontWeight" Value="Bold"/>
                        <Setter Property="Foreground" Value="Black"/>
                    </Trigger>
                </Style.Triggers>
            </Style>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="25"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="30"/>
            <RowDefinition Height="30"/>
            <RowDefinition Height="30"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Label Content="Users:" Grid.Row="0" Grid.Column="0"/>
        <local:CustomDataGrid x:Name="UsersDataGrid" ItemsSource="{Binding UsersViewSource.View}" SelectionMode="Extended" AlternatingRowBackground="LightBlue" AlternationCount="2"
                              SelectionUnit="FullRow" IsReadOnly="True" SnapsToDevicePixels="True" AutoGenerateColumns="False" Grid.Row="1" Grid.Column="0" CanUserAddRows="False" CanUserDeleteRows="False" CanUserReorderColumns="False"
                              SelectedItemsList="{Binding SelectedUsers, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsSynchronizedWithCurrentItem="False" CellStyle="{StaticResource CustomDataGridCellStyle}">
            <local:CustomDataGrid.Columns>
                <DataGridTextColumn Header="Nickname:" Width="*" Binding="{Binding Nickname}"/>
                <DataGridTextColumn Header="Age:" Width="*" Binding="{Binding Age}"/>
            </local:CustomDataGrid.Columns>
        </local:CustomDataGrid>
        <Button Grid.Row="2" Grid.Column="0" Margin="5" MaxWidth="80" MinWidth="80" Content="Delete 1st row" Command="{Binding DeleteFirstUserCommand}"/>
        <Button Grid.Row="3" Grid.Column="0" Margin="5" MaxWidth="80" MinWidth="80" Content="Delete last row" Command="{Binding DeleteLastUserCommand}"/>
        <Button Grid.Row="4" Grid.Column="0" Margin="5" MaxWidth="80" MinWidth="80" Content="Initialize Grid" Command="{Binding InitializeListCommand}"/>
    </Grid>
</Window>


Файл MainWindow.язык XAML.в CS:
using System;
using System.Collections;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;

namespace DeleteFirstRowIssue
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new UsersViewModel();
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            UsersViewModel uvm = (UsersViewModel)DataContext;
            if (uvm.SelectedUsers.Count > 0)
            {
                StringBuilder sb = new StringBuilder(uvm.SelectedUsers.Count.ToString() + " selected user(s):\n");
                foreach (UserModel um in uvm.SelectedUsers)
                {
                    sb.Append(um.Nickname + "\n");
                }
                MessageBox.Show(sb.ToString());
            }
            base.OnClosing(e);
        }
    }

    public class UsersViewModel : INotifyPropertyChanged
    {
        private IList selectedUsers;
        public IList SelectedUsers
        {
            get { return selectedUsers; }
            set
            {
                selectedUsers = value;
                OnPropertyChanged("SelectedUsers");
            }
        }

        public CollectionViewSource UsersViewSource { get; private set; }
        public ObservableCollection<UserModel> Users { get; set; }
        public ICommand DeleteFirstUserCommand { get; }
        public ICommand DeleteLastUserCommand { get; }
        public ICommand InitializeListCommand { get; }
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); }

        public UsersViewModel()
        {
            SelectedUsers = new ArrayList();
            Users = new ObservableCollection<UserModel>();
            UsersViewSource = new CollectionViewSource() { Source = Users };
            InitializeListCommand = new RelayCommand(p => Users.Count == 0, p => InitializeList());
            InitializeListCommand.Execute(null);
            DeleteFirstUserCommand = new RelayCommand(p => Users.Count > 0, p => DeleteFirstUser());
            DeleteLastUserCommand = new RelayCommand(p => Users.Count > 0, p => DeleteLastUser());
        }

        private void InitializeList()
        {
            Users.Add(new UserModel() { Nickname = "John", Age = 35 });
            Users.Add(new UserModel() { Nickname = "Jane", Age = 29 });
            Users.Add(new UserModel() { Nickname = "Mark", Age = 59 });
            Users.Add(new UserModel() { Nickname = "Susan", Age = 79 });
            Users.Add(new UserModel() { Nickname = "Joe", Age = 66 });
            Users.Add(new UserModel() { Nickname = "Nina", Age = 29 });
            Users.Add(new UserModel() { Nickname = "Selma", Age = 44 });
            Users.Add(new UserModel() { Nickname = "Katrin", Age = 24 });
            Users.Add(new UserModel() { Nickname = "Joel", Age = 32 });
        }

        private void DeleteFirstUser()
        {
            ListCollectionView lcw = (ListCollectionView)UsersViewSource.View;
            lcw.RemoveAt(0);
        }

        private void DeleteLastUser()
        {
            ListCollectionView lcw = (ListCollectionView)UsersViewSource.View;
            lcw.RemoveAt(lcw.Count - 1);
        }
    }

    public class UserModel
    {
        public string Nickname { get; set; }
        public int Age { get; set; }
    }

    public class CustomDataGrid : DataGrid
    {
        public static readonly DependencyProperty SelectedItemsListProperty = DependencyProperty.Register("SelectedItemsList", typeof(IList), typeof(CustomDataGrid), new PropertyMetadata(null));
        public IList SelectedItemsList
        {
            get { return (IList)GetValue(SelectedItemsListProperty); }
            set { SetValue(SelectedItemsListProperty, value); }
        }

        public CustomDataGrid() { SelectionChanged += CustomDataGrid_SelectionChanged; }
        void CustomDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e) { SelectedItemsList = SelectedItems; }
    }

    public class RelayCommand : ICommand
    {
        private Predicate<object> canExecute;
        private Action<object> execute;

        public RelayCommand(Predicate<object> canExecute, Action<object> execute)
        {
            this.canExecute = canExecute;
            this.execute = execute;
        }

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        public bool CanExecute(object parameter) { return canExecute(parameter); }
        public void Execute(object parameter) { execute(parameter); }
    }
}


ОБНОВЛЕНИЕ:

У меня есть решение здесь

Что я уже пробовал:

Я что-то пробовал, но не уверен, что у меня есть хорошая идея, где искать решение.

0 Ответов