在给DataGrid的RowStyle中,我喜欢将IsSelected依赖属性绑定到我数据源上的IsSelected上
<Window.Resources> <Style x:Key="DataGridRowStyle1" TargetType="{x:Type DataGridRow}"> <Setter Property="IsSelected" Value="{Binding IsSelected,Mode=TwoWay}"></Setter> </Style> </Window.Resources> <Grid> <DataGrid ItemsSource="{Binding Persons}" RowStyle="{DynamicResource DataGridRowStyle1}"/> </Grid>
Person.cs
public class Person : INotifyPropertyChanged { private bool _isSelected; public string Name { get; set; } public int Age { get; set; } public bool IsSelected { get { return _isSelected; } set { _isSelected = value; OnPropertyChanged("IsSelected"); } } public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } }
MainWindow.xaml.cs
public partial class MainWindow : Window,INotifyPropertyChanged { private ObservableCollection<Person> _persons; public ObservableCollection<Person> Persons { get { return _persons; } set { _persons = value; OnPropertyChanged("Persons"); } } public MainWindow() { InitializeComponent(); DataContext = this; _persons=new ObservableCollection<Person>(); for (int i = 0; i < 400; i++) { Persons.Add(new Person() { Age=i, Name="HelloWorld"+i }); } } public void OnPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this,new PropertyChangedEventArgs(propertyName)); } } public event PropertyChangedEventHandler PropertyChanged; }
这是全部的源码,运行,点击图中红色方框内的按钮,这是DataGrid自带的一个全选功能
好,问题出来了,一眼看上去,好像所有的IsSelected都勾选上了,但是,使用滚动条往下拖就会发现,下面的偶尔有几个选中,往后就再也没有选中的了。突然想到DataGrid有一个行虚拟的技术,果断就把EnableRowVirtualization="False"设置了一下,全选问题解决了。但是就不能够使用行虚拟技术了,这样条目非常多的时候,加载就非常慢了(不希望使用分页,见谅~)。不希望这样,所有求助大神们帮忙看一下这个奇怪的问题。下面是解决方案,可以直接打开研究
http://files.cnblogs.com/HelloMyWorld/DataGridsBug.rar
谢谢!
这个其实没有啥好讨论的,想要马儿跑,还要马儿不吃草。天底下哪来这么多的好事。
违反逻辑性的命题或需求,直接枪毙了。
说得好,但我总觉得一些效果达不到可能是技术还不倒位。有一些客户的要求确实难以实现,这就不能从技术角度解决问题了。哎~,我挺纠结的
@Bat-Man:
我不是瞎说的,你仔细想想吧。我目前所有的产品都基于互联网,ADSL 512K速度可流畅运行,所以一次性加载500行这种事情根本是没有办法的。目测只有两种方案,
一是分页,二是虚拟加载(也称为服务器模式),实际上只加载用户看见的那几行数据。
采用虚拟加载,你在点击“Check”的时候,如果要求选择全部的500或是5000行甚至500万行。
意味着这时候,要把所有的数据加载出来。要么你就要自己进行这种处理(控件不会帮你做这个事情)
@爱编程的大叔: 嗯,多谢指教,我会好好斟酌下的
主要看了这里
http://stackoverflow.com/questions/6430132/datagrid-isselected-binding-and-scrolling
希望能对遇到同样问题的同学有帮助
Try setting the virtualizationmode to standard on the DataGrid: VirtualizingStackPanel.VirtualizationMode="Standard"
.
这个起作用。
嗯,但是全选之后,你任意取消一个,然后再滚动,就会发现这个问题不是那么简单
我下载了你的例子,我的程序也出现同样的问题。
IsSelected不能设置绑定,这是因为IsSelected是DataGridRow的关联属性,UI虚拟化后,DataGridRow滚动出窗口会被一同销毁导致出错。
需要调用DataGrid的SelectedItems非关联属性就不会出错,但不支持绑定。
我的做法是自定义一个控件包装DataGrid,重新定义ItemsSource、DataGridRow ,监听DataGrid的SelectedChanged事件,将DataGrid的SelectedItems转移新的ItemsSource上,更新DataGridRow的IsSelected属性。
不用改属性,也不用分页,嘻嘻
今天也遇到了这个问题,我讲一下我的思路,当然这种思路也可能是很多人诟病的,哈哈哈,不过我觉得还挺实用的
我主要是利用SelectItems来实现的
保留DataGrid上的SelectionChanged,通过SelectItems来获取选中行的Id集合(List<int>),将所得到的集合直接赋值给ViewModel(的选中Id集合)
xaml.cs中:
ViewModel中:
效果图: