I have a view in my application with huge table like data to display. The data is displayed in two nested UniformGrids. The UniformGrids are ItemPanels in ItemsControls and are bound to some ViewModels. See the following image and some example XAML-Code:
view and viewmodel http://img593.imageshack.us/img593/8825/stackoverflowuniformgri.png
<!-- The green boxes -->
<ItemsControl ItemsSource="{Binding BigCells}">
<ItemsControl.ItemPanel>
<PanelTemplate>
<UniformGrid />
</PanelTemplate>
</ItemsControl.ItemPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<!-- The blue boxes -->
<ItemsControl ItemsSource="{Binding SmallCells}">
<ItemsControl.ItemPanel>
<PanelTemplate>
<UniformGrid />
</PanelTemplate>
</ItemsControl.ItemPanel>
</ItemsControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Now, I want my view to be resizable but this does not perform well at all since every single small box's layout is computed.
This could at least for the boxes size be done only once, since it is equal for all boxes.
What is best practice to display a huge amount of controls in WPF / where could I start optimizing? Keywords would already help me to continue discovering performance optimizations for UniformGrids in WPF.
I've had a similar problem when using a lot of WPF DataGrid
at the same time. It finally came down to two major issues :
Resource Dictionaries
Those can be major bottlenecks if you use basic WPF features without being careful.
In my case, for a single logical scroll in the ItemsControl
that was containing my DataGrids
, I was getting something like 10 millions call to GetValue
and GetValueWithoutLock
on ResourceDictionary. More than 1 second to process.
This major number of ResourceDictionary
accesses was caused by different sources :
ControlTemplates
, and more generally resources placed in some resource dictionaries, and you access them via {DynamicResource ...}
, remove them. Have some static somewhere and acces them directly.Style={x:Null}
on each and every control (if you need a style for a control, set it inline on your control, and add OverridesDefaultStyle = true
)DataTemplate
to apply, WPF will once again browse your resource dictionaries to find a DataTemplate
matching your ViewModels types. Solution is to use a DataTemplate
selector for each and every control binded to a ViewModel, and implement an optimized way to retrieve the correct DataTemplate
. (I personally have some static fields for my dataTemplate that I retrieve only once from a resourceDictionary, and an optimized DataTemplateSelector
that returns them as needed.)Bindings
Bindings are very useful, but very expensive, memory wise and performance wise. In a very sensible environement - from a performance point of view - you can't just use them without being carefull. For exmample, binding can create up to 3 WeakReferences for each binded object, can use reflection, etc. I finally ended up with removing almost all of my binding and plugged event handler on my DataContext's PropertyChanged event. When DataContext
changes on my Controls (you have a DataContextChanged
event) I test if my DataContext
supports INotifyPropertyChanged
, and if it's the case, I attach an event handler on PropertyChanged
event and update properties as needed. (I only had one way bindings, so this is why I chose this way of doing things, but there are other solutions).
It can seems frustrating not using bindings when using MVVM and WPF, but there was actually no way to optimize bindings in my case.
Last thing : if you have Freezable
objects (like Brushes for example), don't hesitate to Freeze
them if you can.
Those are some advices that can help you optimizing your code. You will need a profiler (I always advice using dotTrace as this is the best profiler I ever used) to monitor what's really happening and adapt your according to the results.
Good luck !
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With