提问人:Sinatr 提问时间:7/11/2016 最后编辑:CommunitySinatr 更新时间:6/21/2023 访问量:2330
具有虚拟化功能的 ScrollIntoView 和 ListView
ScrollIntoView and ListView with virtualization
问:
我有(默认情况下虚拟化处于打开状态),它与属性绑定。ListView
ItemsSource
ObservableCollection<Item>
当数据被填充(属性被设置并通知被上升)时,我在分析器中看到 2 个布局峰值,第二个发生在调用之后。listView.ScrollIntoView()
我的理解是:
ListView
通过绑定加载数据,并从索引 0 开始为屏幕上的项目创建数据。ListViewItem
- 然后我打电话给.
listView.ScrollIntoView()
- 现在第二次(创建 s)。
ListView
ListViewItem
如何防止这种去虚拟化发生两次(我不希望之前发生一次)?ScrollIntoView
我试图使用 .ListBox
XAML:
<Grid>
<ListBox x:Name="listBox" ItemsSource="{Binding Items}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsSelected" Value="{Binding IsSelected}" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
<Button Content="Fill" VerticalAlignment="Top" HorizontalAlignment="Center" Click="Button_Click" />
</Grid>
ds]
public class NotifyPropertyChanged : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string property = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}
public class ViewModel : NotifyPropertyChanged
{
public class Item : NotifyPropertyChanged
{
bool _isSelected;
public bool IsSelected
{
get { return _isSelected; }
set
{
_isSelected = value;
OnPropertyChanged();
}
}
}
ObservableCollection<Item> _items = new ObservableCollection<Item>();
public ObservableCollection<Item> Items
{
get { return _items; }
set
{
_items = value;
OnPropertyChanged();
}
}
}
public partial class MainWindow : Window
{
ViewModel _vm = new ViewModel();
public MainWindow()
{
InitializeComponent();
DataContext = _vm;
}
void Button_Click(object sender, RoutedEventArgs e)
{
var list = new List<ViewModel.Item>(1234567);
for (int i = 0; i < 1234567; i++)
list.Add(new ViewModel.Item());
list.Last().IsSelected = true;
_vm.Items = new ObservableCollection<ViewModel.Item>(list);
listBox.ScrollIntoView(list.Last());
}
}
调试 - 性能探查器 - 应用程序时间线...稍等片刻,单击按钮,稍等片刻,关闭窗口。您将看到 2 个带有 .我的目标是只有一个,我不知道怎么做。VirtualizingStackPanel
重现的问题是模拟负载(当创建成本很高时),但我希望它现在能更清楚地说明问题。ListViewItem
答:
Scroll 方法通常不能很好地工作在 .为了解决这个问题,我使用以下解决方案。VirtualizingStackPanel
- 抛弃 .使用普通的 StackPanel 作为面板模板。
VirtualizingStackPanel
- 从这里开始,使 DataTemplate 的外层成为 LazyControl: http://blog.angeloflogic.com/2014/08/lazycontrol-in-junglecontrols.html
- 确保在该 LazyControl 上设置高度。
我通常从这种方法中获得良好的性能。为了使它完全按照您的要求执行操作,您可能需要向 LazyControl 添加一些额外的逻辑,以等待设置某些标志(在调用 scroll 方法之后)。
答案就在你最后的陈述中:
当创建 ListViewItem 时成本高昂
您可以回收项目的布局(只要它们具有相同的布局)。此外,像素滚动使滚动比单位滚动更令人窒息。
<ListBox VirtualizingPanel.VirtualizationMode="Recycling"
VirtualizingPanel.ScrollUnit="Pixel">
我猜你设置Button_Click函数是为了举例;请注意,如果在 ListBox 控件主动使用时将许多项添加到 ObservableCollection 中,则会破坏性能;不幸的是,该类没有 AddRange 函数,因此您需要即兴创作;检查此线程。
评论
ListView
ListView
ScrollIntoView
ScrollIntoView
ListView
ListView