I have an issue with WPF DataGrid
, which drives me crazy.
Let's consider this view model:
public class ViewModel : INotifyPropertyChanged
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsSelected
{
get { return isSelected; }
set
{
System.Diagnostics.Debug.WriteLine("{0}'s IsSelected new value is: {1}", Name, value);
if (isSelected != value)
{
isSelected = value;
OnPropertyChanged("IsSelected");
}
}
}
private bool isSelected;
// INPC implementation
}
... this XAML:
<Window x:Class="WpfApplication5.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<DataGrid ItemsSource="{Binding}" IsReadOnly="True" AutoGenerateColumns="False"
SelectionMode="Extended" SelectionUnit="FullRow">
<DataGrid.ItemContainerStyle>
<Style TargetType="{x:Type DataGridRow}">
<Setter Property="IsSelected" Value="{Binding IsSelected}"/>
</Style>
</DataGrid.ItemContainerStyle>
<DataGrid.Columns>
<DataGridCheckBoxColumn Header="Is selected" Binding="{Binding IsSelected}"/>
<DataGridTextColumn Header="Id" Binding="{Binding Id}"/>
<DataGridTextColumn Header="Name" Width="*" Binding="{Binding Name}"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
...and this code-behind:
public partial class MainWindow : Window
{
private IList<ViewModel> GenerateViewModels()
{
var viewModels = new List<ViewModel>();
for (var i = 0; i < 100; i++)
{
viewModels.Add(new ViewModel
{
Id = i,
Name = string.Format("Item {0}", i)
});
}
return viewModels;
}
public MainWindow()
{
InitializeComponent();
DataContext = GenerateViewModels();
}
}
Case 1.
- Select Item 0. Item 0 is selected, check box is checked.
- Scroll grid's content to hide Item 0. Let the Item 6 be on top of visible area.
- Select Item 10. Item 10 is selected, check box is checked.
- Scroll up to Item 0.
- Select Item 0. Item 10 is selected, check box is not checked.
Debug output:
Item 0's IsSelected new value is: True
Item 0's IsSelected new value is: False
Item 10's IsSelected new value is: True
Item 10's IsSelected new value is: False
Case 2.
- Restart application.
- Select several items on top of grid (e.g., three first items). Items are selected, check boxes are checked.
- Scroll grid's content to hide Item 0. Let the Item 6 be on top of visible area.
- Select Item 10. Item 10 is selected, check box is checked.
- Scroll up to Item 0.
- Item 0 and Item 1 are still checked. Item 2 isn't checked. All of three first items aren't selected.
Debug output:
Item 0's IsSelected new value is: True
Item 1's IsSelected new value is: True
Item 2's IsSelected new value is: True
Item 2's IsSelected new value is: False
Item 10's IsSelected new value is: True
The problem is reproducing, when the selection mode is extended. When it is single, everything works fine.
Questions:
1. Am I missing something?
2. Anybody knows a workaround?
UPDATE.
I've added SelectionChanged
event handler for the grid:
private void MyGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.AddedItems != null)
{
foreach (var item in e.AddedItems.Cast<ViewModel>())
{
System.Diagnostics.Debug.WriteLine("** Item {0} is added to selection.", item.Id);
}
}
if (e.RemovedItems != null)
{
foreach (var item in e.RemovedItems.Cast<ViewModel>())
{
System.Diagnostics.Debug.WriteLine("** Item {0} is removed from selection.", item.Id);
}
}
e.Handled = true;
}
Debug output says, that SelectedItems
collection is updated properly. E.g., for the first case output will be:
Item 0's IsSelected new value is: True
** Item 0 is added to selection.
Item 0's IsSelected new value is: False
Item 10's IsSelected new value is: True
** Item 10 is added to selection.
** Item 0 is removed from selection.
Item 10's IsSelected new value is: False
** Item 0 is added to selection.
** Item 10 is removed from selection.
But the bound data property IsSelected
isn't updated!
At least, one workaround is found, and its related to the question's update.
Let's modify
SelectionChanged
event handler a little:But it's definitely a bug in
DataGrid
, isn't it?I tried it and I think you need to set the isSelected to false to both condition. It works for me. But thanks for the initial solution! It helped me a lot.