WPF performance for large number of elements on the screen
Im currently trying to create a Scene in WPF where I have around 250 controls on my screen and the user can Pan and Zoom in and out of these controls using the mouse.
I have run the WPF Performance Suite tools on the application when there are a large number of these controls on the screen (i.e. when the user has zoomed right out) the FPS drops down to around 15 which is not very good.
Here is the basic outline of the XAML:
<Window>
<Window.Resources>
<ControlTemplate x:Key="LandTemplate" TargetType="{x:Type local:LandControl}">
<Canvas>
<Path Fill="White" Stretch="Fill" Stroke="Black" StrokeThickness="1" Width="55.5" Height="74.687" Data="M0.5,0.5 L55,0.5 L55,74.开发者_开发百科187 L0.5,74.187 z"/>
<Canvas x:Name="DetailLevelCanvas" Width="24.5" Height="21" Canvas.Left="15.306" Canvas.Top="23.972">
<TextBlock Width="21" Height="14" Text="712" TextWrapping="Wrap" Foreground="Black"/>
<TextBlock Width="17.5" Height="7" Canvas.Left="7" Canvas.Top="14" Text="614m2" TextWrapping="Wrap" FontSize="5.333" Foreground="Black"/>
</Canvas>
</Canvas>
</ControlTemplate>
</Window.Resources>
...
<local:LandControl Width="55.5" Height="74.552" Canvas.Top="xxx" Template=" {StaticResource LandTemplate}" RenderTransformOrigin="0.5,0.5" Canvas.Left="xxx">
<local:LandControl Width="55.5" Height="74.552" Canvas.Top="xxx" Template=" {StaticResource LandTemplate}" RenderTransformOrigin="0.5,0.5" Canvas.Left="xxx">
<local:LandControl Width="55.5" Height="74.552" Canvas.Top="xxx" Template=" {StaticResource LandTemplate}" RenderTransformOrigin="0.5,0.5" Canvas.Left="xxx">
<local:LandControl Width="55.5" Height="74.552" Canvas.Top="xxx" Template=" {StaticResource LandTemplate}" RenderTransformOrigin="0.5,0.5" Canvas.Left="xxx">
... and so on...
</Window>
Ive tried to minimise the details in the control template and I even did a massive find and replace of the controls to just put their raw elements inline instead of using a template, but with no noticeable performance improvements.
I have seen other SO questions about this and people say to do custom drawing, but I dont really see how that make sense when you have to zoom and pan like I do.
If anyone can help out here, that would be great!
Mark
This may sound trite but - There is no free lunch.
I have worked on [this][1] for the past two years. That product consists of 4 browsers whose interfaces are primarily ZUIs. All but the Atlas use Visuals for their graphic rendering and there were a lot of lessons learned and a few deadends.
FrameworkElements are not your friend. The FE engine on a modern GFX card and CPU maxes out at about 500-600 elements, but it depends on their complexity. FE's are about 10x as heavy as Visuals.
Text will significantly impact your framerate. Rendering curves are expensive See [Robby Ingebretsens post][4] for hints on using animated text
Culling is important, but adding/removing from the VisualTree is expensive. Collapsing/Hiding is kind of a compromise.
In WPF 3.5 you have 2 choices - Program down to the Visuals layer or use something like the [Planerator][2] then manipulate the camera to Pan and Zoom but it requires your users have a good gfx card.
In WPF 4.0 things are much better due to something called [Cached Composition][3]. It works for the same reason the Planerator works. The GFX card is rendering your controls to a bitmap and is panning zooming the bitmap.
Using this in 4,0 is easy - Setup .CacheMode
for your most expensive FrameworkElements and things will get a lot faster. You also have the ability to control how text is anti-aliased and the scales at which bitmaps will get regenerated (EnableClearType
and RenderAtScale
)
In my Atlas browser I could display well over 700 pieces of text + simple rectangles without losing interactivity of panning and zooming. Before 4 the map was unusable.
Getting better interactive performance takes time, targets and measurement. Good luck.
[Kael Rowan][5] has an excellent series of articles on a ZoomableCanvas he is working on. It uses a Quadtree and PriorityQueue for implementation and will let you implement semantic zoom.
Update: 8-07-10 Added Text hints and ZoomableCanvas links [1]: http://globible.com [2]: https://learn.microsoft.com/en-us/archive/blogs/greg_schechter/ [3]: https://learn.microsoft.com/en-us/dotnet/api/system.windows.media.bitmapcache?redirectedfrom=MSDN&view=net-5.0 [4]: https://web.archive.org/web/20101210104554/http://blog.nerdplusart.com:80/archives/making-the-most-of-silverlight-text-rendering? [5]: https://learn.microsoft.com/en-us/archive/blogs/kaelr/
You should be able to use custom drawing in combination with Transformations to achieve the zooming and panning you need. You'll probably need to do some basic culling to prevent elements that are not within the viewport from rendering...but the transformation capabilities of WPF are pretty rich, and you should gain a decent amount of performance with it.
Transforms Overview
How to: Scale an Object
How to: Translate an Element
精彩评论