DataGrid row selection bug
-
Monday, August 09, 2010 1:23 PM
I created WPF Application (VS 2010, .NET 4) project, you can reproduce this through copying a code into the corresponding files.
Code for MainWindow.xaml:
< Window x:Class = " WpfBadDataGridRowIsSelectedBinding.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 " ResizeMode = " NoResize " > < Grid > < DataGrid ItemsSource = " {Binding List} " AutoGenerateColumns = " False " SelectionMode = " Extended " IsReadOnly = " True " > < DataGrid.Columns > < DataGridTextColumn Width = " * " Header = " Number " Binding = " {Binding Number, Mode=OneWay} " /> < DataGridCheckBoxColumn Width = " * " Header = " IsSelected " Binding = " {Binding IsSelected, Mode=TwoWay} " /> </ DataGrid.Columns > < DataGrid.RowStyle > < Style TargetType = " DataGridRow " > < Setter Property = " IsSelected " Value = " {Binding IsSelected, Mode=TwoWay} " /> </ Style > </ DataGrid.RowStyle > </ DataGrid > </ Grid > </ Window >
Code for MainWindow.xaml.cs:
namespace WpfBadDataGridRowIsSelectedBinding { using System.Collections; using System.Collections.ObjectModel; using System.ComponentModel; /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow { private readonly ObservableCollection<SimpleViewModel> list = new ObservableCollection<SimpleViewModel>(); public MainWindow() { InitializeComponent(); this .DataContext = this ; for (var i = 0; i < 100; i++) { this .list.Add(new SimpleViewModel(i)); } } public IEnumerable List { get { return this .list; } } private sealed class SimpleViewModel : INotifyPropertyChanged { private readonly int number; private bool isSelected; public SimpleViewModel(int number) { this .number = number; } public int Number { get { return this .number; } } public bool IsSelected { get { return this .isSelected; } set { if (value == this .isSelected) { return ; } this .isSelected = value; this .OnPropertyChanged("IsSelected" ); } } #region INotifyPropertyChanged Members public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string propertyName) { var handler = this .PropertyChanged; if (handler != null ) { handler(this , new PropertyChangedEventArgs(propertyName)); } } #endregion } } }
If I click the first row in DataGrid after run then the corresponding checkbox in the column "IsSelected" is checked, and this is OK. The checking works for second, third.. etc rows of the first page. The second page starts from the 15th row and there I have a problem. If I click row 20 the corresponding checkbox isn't checked, the same with row 21, 22 and so on. And if I scroll DataGrid to the end and return scrolling to row 0 then click the row I also don't see checked checkbox, and now this be on all rows in DataGrid.
What have I done wrong?
I doubt whether you have testers?
All Replies
-
Monday, August 09, 2010 2:28 PM
Interesting.
I think you should make the relative binding one way only(OneWay and OneWayToSource). It works when I changed your code to:
<DataGrid ItemsSource="{Binding List}" AutoGenerateColumns="False" SelectionMode="Extended" IsReadOnly="True" > <DataGrid.Columns> <DataGridTextColumn Width="*" Header="Number" Binding="{Binding Number, Mode=OneWay}" /> <DataGridCheckBoxColumn Width="*" Header="IsSelected" Binding="{Binding IsSelected, Mode=OneWay}" /> </DataGrid.Columns> <DataGrid.RowStyle> <Style TargetType="DataGridRow"> <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=OneWayToSource,UpdateSourceTrigger=PropertyChanged}" /> </Style> </DataGrid.RowStyle> </DataGrid> -
Monday, August 09, 2010 3:01 PMThank you, Rulin Hong, but I'am need TwoWay mode.
-
Monday, August 09, 2010 3:15 PM
I retest it that it works for twoway if you set up UpdateSourceTrigger=PropertyChanged in
<
Style TargetType="DataGridRow">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />
-
Monday, August 09, 2010 3:35 PM
Not completely correct. Select the row 0, then select row 1 with Ctrl, scroll to end, and select the row 99 without Ctrl, and now scroll to begin,
voila, the row 0 still selected...
-
Monday, August 09, 2010 8:10 PM
And another code with slight modifications:
Code for MainWindow.xaml:
<Window x:Class="WpfBadDataGridRowIsSelectedBinding.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" ResizeMode="NoResize"> <DockPanel LastChildFill="True"> <StackPanel DockPanel.Dock="Top" Margin="5" Orientation="Horizontal"> <Button Height="23" Content="Select" Click="Button_Click"/> </StackPanel> <DataGrid ItemsSource="{Binding List}" AutoGenerateColumns="False" SelectionMode="Extended" IsReadOnly="True"> <DataGrid.Columns> <DataGridTextColumn Width="*" Header="Number" Binding="{Binding Number, Mode=OneWay}" /> <DataGridCheckBoxColumn Width="*" Header="IsSelected" Binding="{Binding IsSelected, Mode=TwoWay}" /> </DataGrid.Columns> <DataGrid.RowStyle> <Style TargetType="DataGridRow"> <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" /> </Style> </DataGrid.RowStyle> </DataGrid> </DockPanel> </Window>
Code for MainWindow.xaml.cs:
Start the application, click button "Select", and scroll down, nice, huh?namespace WpfBadDataGridRowIsSelectedBinding { using System.Collections; using System.Collections.ObjectModel; using System.ComponentModel; /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow { private readonly ObservableCollection<SimpleViewModel> list = new ObservableCollection<SimpleViewModel>(); public MainWindow() { InitializeComponent(); this.DataContext = this; for (var i = 0; i < 100; i++) { this.list.Add(new SimpleViewModel(i)); } } public IEnumerable List { get { return this.list; } } private void Button_Click(object sender, System.Windows.RoutedEventArgs e) { for (var i = 0; i < list.Count; i += 2) { this.list[i].IsSelected = true; } } private sealed class SimpleViewModel : INotifyPropertyChanged { private readonly int number; private bool isSelected; public SimpleViewModel(int number) { this.number = number; } public int Number { get { return this.number; } } public bool IsSelected { get { return this.isSelected; } set { if (value == this.isSelected) { return; } this.isSelected = value; this.OnPropertyChanged("IsSelected"); } } #region INotifyPropertyChanged Members public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string propertyName) { var handler = this.PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(propertyName)); } } #endregion } } }
If you replace the style DataGridRow to:
<Style TargetType="DataGridRow"> <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> </Style>
So it will not change anything. -
Thursday, August 12, 2010 8:43 AMModerator
Hi Shuralex,
This problem is caused by the VisualizingStackPanel, set the VirtualizingStackPanel.IsVirtualizing as false will solve this problem.
Something likes the follows:
<DataGrid ItemsSource="{Binding List}" AutoGenerateColumns="False" SelectionMode="Extended" IsReadOnly="True" VirtualizingStackPanel.IsVirtualizing="False">
<DataGrid.Columns>
<DataGridTextColumn Width="*" Header="Number" Binding="{Binding Number, Mode=OneWay}" />
<DataGridCheckBoxColumn Width="*" Header="IsSelected" Binding="{Binding IsSelected, Mode=TwoWay}" />
</DataGrid.Columns>
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
</Style>
</DataGrid.RowStyle>
</DataGrid>
Hope this helps.
Best regards,
Kevin Pan
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.- Marked As Answer by Kevin PanModerator Tuesday, August 17, 2010 2:15 AM
-
Thursday, August 12, 2010 9:24 AM
Hi Kevin,
Thank you, I know about it, it just slowly working on real data sources. Temporarily did. I am writing now, "DataGrid" based on
ListBox (selection there is OK) -
Tuesday, July 12, 2011 9:16 PMI can't believe this. O.O Not the only one with a bug there.
Silvernex Software > Consulting and Development!

