我会保持简洁。我有一个实现ItemTemplate的ListBox。 DataTemplate包含一个复选框。我加载约2000项。我检查前5项,滚动到底部并选择最后5项。然后我向上滚动到顶部项目并注意到我的前5个检查项目已被修改。
<Window
x:Class="CheckItems.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CheckItems"
Title="Window1" Height="300" Width="300"
>
<DockPanel>
<StackPanel DockPanel.Dock="Bottom" >
<Button Content="Test" Click="Button_Click"/>
</StackPanel>
<ListBox DockPanel.Dock="Left"
x:Name="users"
ItemsSource="{Binding Path=Users}"
>
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox>
<TextBlock Text="{Binding Path=Name}"/>
</CheckBox>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DockPanel>
</Window>
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
namespace CheckItems
{
public partial class Window1 : Window
{
ViewModel controller;
public Window1()
{
DataContext = controller = new ViewModel();
InitializeComponent();
controller.Users = LoadData();
}
private List<User> LoadData()
{
var newList = new List<User>();
for (var i = 0; i < 2000; ++i)
newList.Add(new User { Name = "Name" + i, Age = 100 + i });
return newList;
}
private void Button_Click(object sender, RoutedEventArgs e)
{ }
}
public class User
{
public string Name { get; set; }
public int Age { get; set; }
}
public class ViewModel : INotifyPropertyChanged
{
private List<User> users;
public event PropertyChangedEventHandler PropertyChanged;
public List<User> Users
{
get { return users; }
set { users = value; NotifyChange("Users"); }
}
protected void NotifyChange(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
希望除此之外还有一个很好的解释 - 这是一个MS错误。这发生在.NET 3.5和4.0中。当VirtualingStackPanel.IsVirtualizing设置为false时,不会发生此行为,但在现实世界中,无虚拟化加载会很痛苦。
一些见解会很好。
提前致谢,
Andres Olivares
答案 0 :(得分:2)
虚拟化面板重新使用其中的控件,并在滚动时简单地替换控件后面的DataContext
。这意味着当您滚动时,控件的状态(例如IsChecked
)将被重置,除非该状态绑定到DataContext中的某些内容。
例如,如果一次只能显示2000个项目中的10个项目,那么WPF将只渲染其中的14个项目(滚动缓冲区的额外项目),并在滚动和替换时简单地重复使用这14个项目控件后面DataContext
。
如果禁用虚拟化,则会禁用此回收行为。这意味着WPF将呈现2000个项目而不是14个项目,这就是性能如此糟糕的原因。这也意味着CheckBoxes将保持检查状态,因为它们的状态未被重置。
要解决此问题,我建议您向User对象添加IsSelected
属性,并将CheckBox.IsChecked
绑定到该对象。