windows phone ListBox 的 bug

最近在使用windows phone 中Listbox的过程中,发现了一个ListBox的bug

场景模拟:

 有一个用于绑定的Person 类

 public class Person
    {
        public string Name { get; set; }

        public bool Female { get; set; }
    }

页面上有一个ListBox

<ListBox x:Name="lst" ItemsSource="{Binding}" ScrollViewer.VerticalScrollBarVisibility="Visible">               
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="{Binding Name}"/>
                            <CheckBox IsChecked="{Binding Female}" Content="Female"/>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

 

在page的loaded事件给ListBox添加200条数据

 List<Person> Persons = new List<Person>();

 void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            for (int i = 0; i < 200; i++)
            {
                Person person = new Person();
                person.Name = string.Format("name:{0}", i.ToString());
                person.Female = false;

                Persons.Add(person);
            }

            lst.DataContext = Persons;
        }

运行app,勾选前面6个CheckBox,向下滑动ListBox,会发现下面断断续续的也勾选了Checkbox,刚开始以为是我的绑定写的有问题,勾选一个导致多个CheckBox勾选,后来通过加断点监测,我选中一个CheckBox,只会触发一次CheckBox的Checked事件,但是往下滑动的时候还会勾选多个,于是怀疑是ListBox的问题,当ListBox的项较多时,ListBox会启用一种叫做虚拟化的机制,把虚拟化去掉试试:

<ListBox x:Name="lst" ItemsSource="{Binding}" ScrollViewer.VerticalScrollBarVisibility="Visible">
                <ListBox.ItemsPanel>
                    <ItemsPanelTemplate>
                        <StackPanel/>
                    </ItemsPanelTemplate>
                </ListBox.ItemsPanel>
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="{Binding Name}"/>
                            <CheckBox IsChecked="{Binding Female}" Content="Female"/>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

虚拟化去掉之后就ok了,但是问题又来了,由于在我的app中有几百个item,ListBox需要把每个Item渲染完才显示,所以会很慢,而且内存达到了200多M,很显然去掉虚拟化不可取,难道只能手动写延迟加载吗?为了一个这个小的功能单独写一个控件得不偿失,于是继续试验,偶然发现如果CheckBox的IsChecked属性采用的绑定模式是双向绑定则ok

<ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="{Binding Name}"/>
                            <CheckBox IsChecked="{Binding Female,Mode=TwoWay}" Content="Female"/>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>

这样可以解决选中一个多个CheckBox选中的情况,好吧,问题初步解决了,在我的app中,我回到上一页,然后又进入这一页,又出现了一个奇怪问题(我把选中项的状态保存到本地,每次进该列表的时候会读取相应设置,初始化列表状态),选中的项出现了错乱,而且规律不一定,难道是我的代码真出问题了。我给CheckBox添加了Checked,UnChecked事件,发现我在向下滑动ListBox的过程中会不规律的触发CheckBox的Checked,UnChecked事件,但是在这个过程中我并没有点击任何CheckBox,难道ListBox真不ok吗?嗯,同事一句话提醒了我,可以用CheckBox的Click事件试一下,我把本来要在Checked,UnChecked事件处理的事件拿出来放到Click事件处理

 private void CheckedHandler()
        {

        }

        private void UnCheckBoxHandler()
        {

        }

        private void CheckBox_Click(object sender, RoutedEventArgs e)
        {
            CheckBox checkBox = sender as CheckBox;
            if (checkBox != null)
            {
                if (checkBox.IsChecked.Value)
                    CheckedHandler();
                else
                    UnCheckBoxHandler();
            }
        }

 

到这里,才把所有的问题解决到。

关于这个问题的原因我只是猜测了一些原因,由于没有官方文档,就不献丑了。不知道微软能不能修正ListBox的这个Bug。

 

 

 

demo下载地址:http://dl.vmall.com/c0rrwnk4rx

posted on 2013-06-08 15:48  其实,我是一个程序员.  阅读(417)  评论(4编辑  收藏  举报