我的问题是我需要添加很多项目到WPF中的列表框。在WinForms中,您只需使用BeginUpdate();方法,添加一切,最后使用EndUpdate();方法。WPF中BeginUpdate的等价物?
那么,我将如何停止在WPF列表框中的绘图,直到每个项目被添加,然后一口气绘制所有东西?
我的问题是我需要添加很多项目到WPF中的列表框。在WinForms中,您只需使用BeginUpdate();方法,添加一切,最后使用EndUpdate();方法。WPF中BeginUpdate的等价物?
那么,我将如何停止在WPF列表框中的绘图,直到每个项目被添加,然后一口气绘制所有东西?
这听起来像你可能会编程式地将项目添加到您的列表框一个接一个。更好的方法是将要显示的项目存储在模型中,并将模型绑定到列表框的数据上下文。这将允许WPF负责渲染更新。
如果您将XAML代码片段和代码添加到问题中(向我们展示您目前正在做什么),我们可能会提供更好的答案。
编辑:增加了一个非常简单的例子。
下面是一个将视图模型绑定到主窗口(视图)的示例,然后XAML声明ListBox的数据绑定到视图模型的Numbers属性。
MainViewModel.cs
public class MainViewModel
{
public IEnumerable<int> Numbers
{
get { return Enumerable.Range(1, 1000); }
}
}
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"
Height="350"
Width="525"
>
<ListBox ItemsSource="{Binding Numbers}"/>
</Window>
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainViewModel();
}
}
如果你刚刚开始使用WPF,我可以高度推荐Windows Presentation Foundation Unleashed Adam Nathan。这是一本很棒的书,它的颜色可以启动。之后阅读其他书籍就像使用Visual Studio后回到记事本一样。
欲了解更多关于此Model-View-ViewModel的内容,请参阅Josh Smith的书Advanced MVVM。
正确使用调度程序。
您必须从Dispatcher线程添加事件到您的ListBox(或其数据源),否则UI将爆炸。当你这样做时,你已经在该线程的方法中,或者(希望更有可能)你在后台线程中并使用Dispatcher.BeginInvoke
来添加项目。
当您将更新踢到分派器时,请使用Dispatcherpriority.Normal
作为优先级。调度员有一个工作项目队列,并且您的项目将推入(可能是令人惊讶的)高的队列中。
当底层数据发生更改时,WPF运行的更新数据绑定的代码位运行在DispatcherPriority.DataBind
之下,该值低于Normal
。这意味着在添加所有项目之前,数据绑定通常不会更新(或者,如果项目需要很长时间才能添加,则可能会在分派器在添加项目之间空闲时发生)。
实际呈现您的控件的代码位(例如,绑定信号发生更新时)会在DispatcherPriority.Render
处运行,并且优先级低于绑定。这意味着只有在分派器用完绑定才能更新时,您的控件才会呈现,而这反过来只会在分派器用完了要处理的项目添加时才会发生。
如果这听起来很奇怪,请记住每个图层(更新 - 绑定 - 渲染)会在下面的图层上设置隐喻标志 - 您不会获得10个绑定,然后发生10个渲染。如果你的物品添加速度很快,你会得到所有的增加,然后是一个绑定和一个渲染 - 这是完美的。
基本上:如果你使用Dispatcher作为它的意图,你将没有什么可担心的。渲染作为调度员相对较低的优先级似乎是“错误的”,但实际上,它非常聪明:-)
看到您正在处理大型列表,您可能需要查看WPF UI虚拟化。这里是一个很好一系列关于它的博客帖子:
http://blogs.msdn.com/dancre/archive/tags/VirtualizingTilePanel/default.aspx
通常你的项目的收集和有收集数据绑定到列表框控件。如果正确完成,列表框不应刷新正在添加且不可见的项目。
是的,我以编程方式将项目添加到列表框。因为我还没有编码整个应用程序,我只是测试如何使用列表框和以下代码: for(int i = 0; i <1000; i ++) { lbQuery.Items.Add(i); } 无论如何,你能给我一个解决方案的代码示例吗? – Lith 2010-05-04 22:49:20
+1,首先将它们构建到列表中会更好。除非这是不可能的,否则你将不得不忍受每增加一次重绘的开销。 – 2010-05-04 22:49:52
如果您可以一次快速填充整个列表,那么您应该在绑定之前这么做......如果没有,那么如果您可以一次添加批处理或类似方法,则不必为每次添加重绘。 – 2010-05-04 22:52:58