Проблема с 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); } } }
ОБНОВЛЕНИЕ:
У меня есть решение здесь
Что я уже пробовал:
Я что-то пробовал, но не уверен, что у меня есть хорошая идея, где искать решение.