Top 10 WPF Performance Tips

Windows Presentation Foundation provides a very confortable way to develop rich user experiences. A drop shadow for example can added by inserting two simple lines of XML. But this simplicity can also mislead us to overuse them. This leads to performance issues. The following tipps may help you to avoid or fix them.

  1. Dispatch expensive calls either within the UI thread with a lower DispatcherPriority by calling Dispatcher.BeginInvoke() or to a background thread by using a BackgroundWorker to keep the UI responsive.
  2. Fix binding errors because they consume a lot of time, trying to resolve the path error, including searching for attached properties. You can find them by looking for System.Windows.Data Error in the Visual Studio output log.
  3. Reduce the number of visuals by removing unneeded elements, combining layout panels and simplifying templates. This keeps the memory footprint small and improves the rendering performance.
  4. Prevent Software Rendering. The use of transparent windows by setting AllowsTransparency to true or using old BitmapEffects can cause WPF to render the UI in software on Windows XP, which is much slower.
  5. Load resources when needed. Even thow it's the most comfortable way to merge all resources on application level it can also cost performance by loading all resources at startup. A better approach is to load only often used resources and load the other on view level.
  6. Virtualize lists and views by using a VirtualizingStackPanel as ItemsPanel for lists. This only creates the visible elements at load time. All other elements are lazy created when they get visible. Be aware that grouping or CanContextScrol="True" prevents virtualization!
  7. Enable Container Recycling. Virtualization brings a lot of performance improvements, but the containers will be disposed and re created, this is the default. But you can gain more performance by recycle containers by setting VirtualizingStackPanel.VirtualizationMode="Recycling"
  8. Freeze Freezables by calling Freeze() in code or PresentationOptions:Freeze="true" in XAML. This reduces memory consumption and improves performance, because the system don't need to monitor for changes.
  9. Disable Assembly localization if you don't need it. By using the [NeutralResourcesLanguageAttribute]. This prevents an expensive lookup for satelite assemblies
  10. Lower the framerate of animations by setting Storyboard.DesiredFrameRate to lower the CPU load. The default is 60 frames/second
  11. Use StreamGeometries instead of PathGeometries if possible to draw complex 2D geometries, because they are much more efficient and consume less memory.

Other articles about WPF performance

http://blogs.msdn.com/b/jgoldb/archive/2007/10/10/improving-wpf-applications-startup-time.aspx 

 

1)一种常见的Validation.Error设置错误导致:“Here’s the type of debug spew that fills the output window:

System.Windows.Data Error: 16 : Cannot get ‘Item[]‘ value (type ‘ValidationError’) from ‘(Validation.Errors)’ (type ” 

错误:

<Style x:Key=”textBoxInError” TargetType=”{x:Type TextBox}”>
<Style.Triggers>
<Trigger Property=”Validation.HasError” Value=”true”>
<Setter Property=”ToolTip”
Value=”{Binding RelativeSource={x:Static RelativeSource.Self},
Path=(Validation.Errors)[0].ErrorContent}”/>
</Trigger>
</Style.Triggers>
</Style>

 如果Validation.Errors为null,则引发exception.

 

The trick is to bind a ContentPresenter’s Content to the CurrentItem of Validation.Errors for the target element.   Binding to the CurrentItem means that we’re  binding to the CurrentItem property of the default ICollectionView that wraps the ReadOnlyObservableCollection<ValidationError> returned by the attached Errors property.  When the current item is non-null, that means there is a validation error; when it is null, there are no validation errors.  We can rely on ICollectionView to safely access the validation error, or not return anything if there are no errors.  That is what prevents the debug spew from pouring out.

 

正确:

<Style x:Key=”textBoxInError” TargetType=”{x:Type TextBox}”>
<Style.Triggers>
<Trigger Property=”Validation.HasError” Value=”true”>
<Setter Property=”ToolTip”
Value=”{Binding RelativeSource={x:Static RelativeSource.Self},
Path=(Validation.Errors).CurrentItem.ErrorContent}”/>
</Trigger>
</Style.Triggers>
</Style>

 

2)Datagird/ListBox : using VisualStackPanel

 

As a little background, the VirtualizingStackPanel’s virtualization scheme basically works like this: generate containers when needed and throw them away when they are no longer in view.  This does solve the memory issue that is created when the panel has a large number of items, but it can still be very expensive to have to recreate and throw away containers every time they go out of view.  Enter container recycling.  Container recycling is a performance optimization to this virtualization scheme.  It basically reuses existing containers so they do not have to be recreated each time they come back into view.

Note that ListBox uses a VSP as its ItemsPanel and sets the VirtualizingStackPanel.IsVirtualizing attached property to true by default.  If you were using ItemsControl directly or creating a custom ItemsControl that uses a VSP as its ItemsPanel, you will need to set both attached properties to get the recycling behavior.

<ItemsControl VirtualizingStackPanel.IsVirtualizing="true" VirtualizingStackPanel.VirtualizationMode="Recycling" …/>

 

<my:DataGrid AutoGenerateColumns="True" ItemsSource="{Binding}" Margin="11,20,8,9" Name="dataGrid1"
                     VirtualizingStackPanel.VirtualizationMode="Recycling" />

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值