首页 新闻 会员 周边

WPF DataGrid 使用自带的全选产生Bug?喜欢研究和讨论的戳进来

0
悬赏园豆:5 [待解决问题]

在给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

谢谢!

UncleNull的主页 UncleNull | 初学一级 | 园豆:3
提问于:2014-07-09 12:07
< >
分享
所有回答(5)
0

这个其实没有啥好讨论的,想要马儿跑,还要马儿不吃草。天底下哪来这么多的好事。

违反逻辑性的命题或需求,直接枪毙了。

爱编程的大叔 | 园豆:30839 (高人七级) | 2014-07-09 14:30

说得好,但我总觉得一些效果达不到可能是技术还不倒位。有一些客户的要求确实难以实现,这就不能从技术角度解决问题了。哎~,我挺纠结的

支持(0) 反对(0) UncleNull | 园豆:3 (初学一级) | 2014-07-09 15:11

@Bat-Man: 

我不是瞎说的,你仔细想想吧。我目前所有的产品都基于互联网,ADSL 512K速度可流畅运行,所以一次性加载500行这种事情根本是没有办法的。目测只有两种方案,

一是分页,二是虚拟加载(也称为服务器模式),实际上只加载用户看见的那几行数据。

采用虚拟加载,你在点击“Check”的时候,如果要求选择全部的500或是5000行甚至500万行。

意味着这时候,要把所有的数据加载出来。要么你就要自己进行这种处理(控件不会帮你做这个事情)

支持(0) 反对(0) 爱编程的大叔 | 园豆:30839 (高人七级) | 2014-07-09 15:20

@爱编程的大叔: 嗯,多谢指教,我会好好斟酌下的

支持(0) 反对(0) UncleNull | 园豆:3 (初学一级) | 2014-07-09 15:42
0

主要看了这里

http://stackoverflow.com/questions/6430132/datagrid-isselected-binding-and-scrolling

希望能对遇到同样问题的同学有帮助

UncleNull | 园豆:3 (初学一级) | 2014-07-09 21:16
0

Try setting the virtualizationmode to standard on the DataGrid: VirtualizingStackPanel.VirtualizationMode="Standard"

这个起作用。

andy-gao | 园豆:209 (菜鸟二级) | 2014-11-04 17:45

嗯,但是全选之后,你任意取消一个,然后再滚动,就会发现这个问题不是那么简单

支持(0) 反对(0) UncleNull | 园豆:3 (初学一级) | 2014-11-04 18:31
0

我下载了你的例子,我的程序也出现同样的问题。

IsSelected不能设置绑定,这是因为IsSelected是DataGridRow的关联属性,UI虚拟化后,DataGridRow滚动出窗口会被一同销毁导致出错。

需要调用DataGrid的SelectedItems非关联属性就不会出错,但不支持绑定。

我的做法是自定义一个控件包装DataGrid,重新定义ItemsSource、DataGridRow ,监听DataGrid的SelectedChanged事件,将DataGrid的SelectedItems转移新的ItemsSource上,更新DataGridRow的IsSelected属性。

ckile | 园豆:202 (菜鸟二级) | 2015-01-15 19:24
0

不用改属性,也不用分页,嘻嘻
今天也遇到了这个问题,我讲一下我的思路,当然这种思路也可能是很多人诟病的,哈哈哈,不过我觉得还挺实用的
我主要是利用SelectItems来实现的
保留DataGrid上的SelectionChanged,通过SelectItems来获取选中行的Id集合(List<int>),将所得到的集合直接赋值给ViewModel(的选中Id集合)
xaml.cs中:

ViewModel中:

效果图:

蓝色迷恋 | 园豆:202 (菜鸟二级) | 2019-06-03 19:45
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册