gpt4 book ai didi

c# - 如何正确改进 ItemsControl 加载并避免卡顿

转载 作者:行者123 更新时间:2023-11-30 12:55:59 25 4
gpt4 key购买 nike

我想知道改进 ItemsControl 加载的正确方法是什么。我想显示加载非常繁重的项目(由于复杂的 XAML)并且我不希望我的 WPF 应用程序卡住。我希望我的项目在渲染后显示出来,并且能够同时与我窗口的其他元素交互(即使它有点慢)。以下是一些假设:

  1. 假设我无法缩短我的项目的加载时间;
  2. 我无法使用虚拟化,因为我需要同时查看所有项目;
  3. View 不会等待后台操作完成,所有工作都在 UI 线程上完成。

我已经找到了解决方法,但我对它不满意,使用 BackgroundWorker 和 sleep :

enter image description here

MainWindow.xaml

<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:local="clr-namespace:WpfApplication1">
<DockPanel>
<Button DockPanel.Dock="Bottom" Content="Click me" Click="OnButtonClick"/>

<ItemsControl ItemsSource="{Binding Items}">
<!-- Items begin to be loaded once the ItemsControl is loaded -->
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<i:InvokeCommandAction Command="{Binding LoadCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Width="25" Height="25" Background="Red" Margin="5">
<local:HeavyItem Content="{Binding}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</DockPanel>
</Window>

ViewModel.cs

public class ViewModel
{
public ICommand LoadCommand { get; protected set; }

public ObservableCollection<int> Items { get; protected set; }

public ViewModel()
{
Items = new ObservableCollection<int>();
LoadCommand = new DelegateCommand(AsyncLoad);
//Load();
}

protected void Load()
{
for (int i = 0; i < 250; i++)
{
Items.Add(i);
}
}

protected void AsyncLoad()
{
var bk = new BackgroundWorker();
bk.DoWork += (s, e) =>
{
for (int i = 0; i < 250; i++)
{
// Sleep 50ms to let the UI thread breeze
Thread.Sleep(50);
Application.Current.Dispatcher.Invoke(DispatcherPriority.Render, (Action)(() =>
{
Items.Add(i);
}));
}
};
bk.RunWorkerAsync();
}
}

HeavyItem.cs(模拟沉重视觉效果的假控件)

public class HeavyItem : ContentControl
{
protected override Size ArrangeOverride(Size finalSize)
{
Thread.Sleep(20);
return base.ArrangeOverride(finalSize);
}
}

This question提供了类似的方法。我不喜欢这种方法,因为:

  1. ViewModel 正在做 View 应该做的事情;
  2. 我使用任意计时器,而项目可能需要更多或更少的时间来呈现,具体取决于计算机。

我认为最好的方法是覆盖 ItemsControl 并告诉 UI 线程在添加项目后进行更新,但我没能做到。有什么线索或想法吗?

最佳答案

关于c# - 如何正确改进 ItemsControl 加载并避免卡顿,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44302328/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com