How to draw 1216 canvas elements without hanging application in WPF

I am developing an application, I want to add some interesting icons. Since I use the beautiful MahApps library, I want to have a visual view of the icons in MahApps.Metro / MahApps.Metro.Resources / Icons.xaml, so I did some string manipulations to capture the x:Key each <Canvas x:Key="appbar_3d_3ds" Width="76" Height="76" Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0"> line. In short, all the string manipulations I did amounted to 1216 instances:

 <controls:Tile Title="appbar_zune" Count="1215" Grid.Row="121" Grid.Column="15" TiltFactor="2" Width="1*" Height="1*" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"> <Rectangle Margin="0" Fill="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=Foreground}"> <Rectangle.OpacityMask> <VisualBrush Stretch="Fill" Visual="{StaticResource appbar_zune}" /> </Rectangle.OpacityMask> </Rectangle> </controls:Tile> 

Note that each copy of <control:Tile has the correct Count , Grid.Row and Grid.Column .

However, I always get a message about Application not responding . Now, as I said, my motive is to get visual information about this collection of cute icons, and instead I get a complete application crash. I just want to know if there is a way to display such a huge collection without knocking anyone out of the computer (note: the system is actually low in RAM: one of my test machines that work inside a virtual box).

+5
source share
1 answer

First, make the Fill binding have Mode = OneWay. I bet you don't need it to be TwoWay, and it could be defalt in your setup. TwoWay binding costs a lot more.

Secondly, consider using a tighter version: Mode = OneTime. Since the icons are unlikely to change, you do not need to track changes at all. This will save you even more resources.

In your case, First + Second probably won't give you a big boost, but it's worth a try and remember.

Third, what about your VisualBrush es? Do they all use the same Visual="{StaticResource appbar_zune}" ? Then why do you create thousands of instances? Instead of copy-paste, create only one instance and include all the elements in one instance. You can save a lot of time and memory.

Fourthly, and most importantly and, as a rule, the greatest acceleration, you have tons of elements. Sure you have a scroll, horizontal or vertical. But how do you create and display this bunch of items? Creating them ALL at once ... is wasteful. They do not fit everyone on the screen, right?

Do you have an ItemsControl element that generates a thousand items? Examine the ItemsPanel property of this ItemsControl and enable virtualizing in this panel. This will snap to the scrollbar, and it will dynamically create only those elements that appear on the screen and destroy elements that extend beyond the screen. Well, I simplified this, but it allows it to work like that. Note that containers, such as a ListBox (and many others), are also an ItemsControl element, so it also applies here.

Or maybe you have a huge explicit XAML file with thousands of controls inside some StackPanel without an ItemsControl? This is not very wise. But ok ... you can enable virtualization on this StackPanel.

Enabling virtualization is usually a good idea if you have dozens of items. Often you have to have a hundred, and this is necessary if you reach thousands or more. However, the cost of virtualization: it very often resets / reinitializes items. If your ItemTemplate is really complicated, virtualization can cause the scrollbar to become โ€œjaggy / laggyโ€, I donโ€™t know how to express it in English, sorry. There may simply not be enough time in the composer's stream to recount and relay all rapidly moving elements. If you encounter this problem, try setting the Element Height to an unchanged, truly fixed constant value. This helps to significantly speed up the layout. but if your ItemTemplate is really an evil complex, this may not help. In such a dead end case, the only option is ... redesign and simplification of the element template.

EDIT:

Of course, all this will not bring you anything if you do not have a scroll bar, and if you are trying to display a ton of objects at the same time. In this case, try to simplify or remove Bindings, Templates, nesting of components (sometimes it is better to calculate positions manually than use three built-in grids), use the rendering cache or (...) .. Sorry, I'm starting to make too many guesses, too many options .

EDIT:

I just noticed Width="1*" and Stretch , so you probably have a grid on top, not a StackPanel. Since you want them to be the same, UniformGrid may have better performance. In addition, with some work, you can also add virtualization to grids:

Oh, and the last word on virtualization: remember that when ScrollView works in virtualization mode, Position no longer taken into account in pixels / points. In v mode, the position of the scroll bar is counted in items , that is, position = 2.5 means that the scroller is halfway through the third element (2 items passed and half more), and not at pos = 2.5 "pixels".

+3
source

Source: https://habr.com/ru/post/1210775/


All Articles