Click here to Skip to main content
15,887,214 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi, the problem I have is following: when first two rows in DataGrid are selected and the first row is deleted, the selected row below becomes the first row and gets deselected. If I sort any of the columns, the selection of that row gets back. If I close the window I get information that deselected row is actually selected (querying content of underlying bound property SelectedUsers in UsersViewModel). Is there anyone who can help or explain me if I did something wrong or this might be a bug. I provided complete source code below. Thanks for help.

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); }
    }
}


UPDATE:

I got the solution here

What I have tried:

I tried something, I am not sure that I have a good idea where to look for a solution.
Posted
Updated 19-Jun-17 22:51pm
v3

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900