Are there in general any known performance issues in WPF related to grid column resizing?
I have an application where I need to do some particular things in a column, but for all the different solutions I find the column resizing gets slow. This applies when I have typically more than 1000 elements in my list, but I assume this isn't too much for WPF..? So; the general question is whether you've experienced slow column resizing, and whether you've found solutions for this? What was causing it?
Some more details about my particular case:
I can have two different things in my columns; ComboBox or TextBlock. The ComboBox should fill the whole column and follow on column resize, and clicking an empty area of a column with a TextBlock should select the row. This is where the problem is. For all solutions I have to this the column resizing gets slow. The only way to make resizing smooth that I've found is by adding a StackPanel outside them with Orientation="Horizontal", but with this I'm unable to achieve the styles described above.
Here are some observations:
Adding style HorizontalContentAlignment="Stretch" to the items of the list makes the ComboBoxes stretch and the TextBlocks clickable, but also column resize slow.
Adding Background="Transparent" to either the StackPanel or the elements that are inserted inside them solves the problem too, but makes resizing slow.
Adding an outer StackPanel with property Orientation="Horizontal" makes resizing smooth, but I'm unable to apply the styles as described.
Have you tried virtualizing the elements in the ListView? When you are virtualizing, the virtualizing panel only creates the visuals for the elements that are in the view. This allows you to have large numbers of items without performance issues like you mention. See VirtualizingStackPanel for more details. Also The Layout System. You can create your own virtualizing panels. If you look up "virtualizing+wpf" on google you'll find lots of hits for virtualizing Canvases, WrapPanels, and etc.
I hope this helps.
Related
I have a DataGrid which has about 100 rows.
Each row has two ComboBoxes.
In my opinion, the scrolling is not smooth and not fast enough.
I would like to have an UI experience like I have in Excel: if you scroll there, the scrolling happens immediately without any delay.
In my DataGrid I have the following:
All the columns have fixed width.
VirtualizingPanel.ScrollUnit="Pixel"
EnableColumnVirtualization="False"
ScrollViewer.IsDeferredScrollingEnabled="True" (I'm not a fan of this one)
The binding ItemsSource is IsAsync=True
The above statements help but it's still not good enough.
I already tried to put the row virtualizing to false. Of course this solves the scrolling problem, but then the loading time takes very long.
Is there a way to set the row virtualizing to true and then the DataGrid rows start loading into memory in the background?
Or is there another option that I'm not considering?
Will the problem be completely solved by not using the ComboBoxes?
The problem was caused by all the comboboxes. I removed all of them and everything is ok now.
I have a DataGrid which has a DataTable set as its ItemsSource.
The DataTable holds 24 columns and ~1600 rows (actually I will have to load alot more rows later on, but for now this is troublesome enough).
Despite setting virtualization for columns and rows active, the DataGrid takes around 30 seconds to display those 1600 rows.
After that, scrolling vertically works fine, horizontally is laggy, though you'd expect it the other way around.
If I run a memory profiler, I can verify that most of the memory used by the application comes from DataGridCells, Borders, ContentPresenters and Textblocks. To me, this indicates that the grid does not virtualize its rows properly.
Can anyone confirm that there's an issues with DataGrid's virtualization? Or is there some sort of infamous trap in the implementation of this control?
Looking forward to any kind of input/suggestions. Thanks :)
I've solved the issue.
My DataGrid was sitting inside a ScrollViewer, in which it would stretch infinitely. So it was fooled into thinking everything was visible, that's why it wouldn't virtualize its items.
I removed the ScrollViewer (DataGrid has scrollbars on its own anyway) and it works flawlessly now.
Hmm, ok I don't know why but obviously I've to add some glue text to post an answer here. Maybe, this SO answer will help you.
Edit
As additional advice I'd like to recommend you to think about your approach. Is it really necessary to add 1.6k+ items to a DataGrid? Perhaps you should think about deferred loading.
I have a ListBox that contains a number of User items that are DataTemplated to appear as UserControls in the ListBox. Each UserControl can be expanded in size. To start with, the ListBox is big enough to display them all in their unexpanded state. The problem that I have is that when a number of these UserControls are expanded together, they extend out of the ListBox's visible area. The ListBox does not recognise this fact and no ScrollBars appear, even when they are set to Visible.
I am using DoubleAnimations to alter the UserControl heights when the user clicks on a button in each one. Is there something that I have to do, or some setting on the ListBox that must be set to get it to register the size changes of the UserControls that represent its items and display ScrollBars when needed?
Edit>>>
I have tracked down the problem to a custom WrapPanel that I am using in the ListBox.ItemsPanel. When I remove it, or replace it with a standard WrapPanel, ScrollBars appear when required. I got the code for the Panel from a good article about creating custom WPF panels. Can anyone see what's missing from the code given in the article and why it might stop the ScrollBars from displaying?
I wonder whether ListBoxes normally do what you are expecting? You might try calling InvalidateMeasure/Layout on the ListBox if you know when the item sizes change, just to see?
I decided to write the custom WrapPanel code again completely and this time it worked correctly! When comparing the new version with the previous version, I could see that a + was missing from a += in a measuring calculation and so the Panel thought that the items were much smaller than they really were... hence no ScrollBars.
So, if you have this problem, check your measuring code carefully.
Seen various examples of WPF applications I've seen the use of the Grid control for almost anything, even simplest things with only 1 column or row.
Also, the WPF templates start with an empty grid.
For me, using StackPanel or DockPanel is less verbose and are better for maintenance (think adding a row later and having to add +1 to all the other rows)
Why is Grid better or what I am missing?
Two words: Star sizing. The Grid makes it possible to size content to the space that contains it without explicitly providing a size for the container. The panel controls don't.
I think part of the reason for Grid being the default element is that it's (slightly) more designer-friendly.
With a Grid, there is no restriction on having multiple elements within a single Grid "cell", which allows a designer with free placement to have the same flexibility as a Canvas, but still have the automatic layout capabilities that Grid (and the other nicer layout controls like StackPanel and DockPanel) contains.
not missing anything. I have quite a lot of grids in my application(s), but not necessarily as top level element and definitely not to the extend you describe.
Could be many people just dont realize that they can remove the initial grid, and instead they put their own control into the grid.
I have found that for more elaborate windows, it is easier to break it down into functional areas that are fairly independent (movement and size wise) of the others. Grids allow those areas to coexist in a single panel, and allow them to be positioned without regard for where other controls are (to some extent).
For instance in a project I am working on right now, I have a window that is going to be a shipping manager. I want three list views (Shipments, Packages, Items) I have a grid control with two columns; one with the Packages list and a grid splitter, the other with a nested grid with the other two lists and a grid splitter.
i have seen many designers break their window down into areas like this, and doing it with anything other than a grid just doesn't work since there are no discreet "cells" that items indirectly live in. Quite a few program windows take this design and so I guess when they had a meeting and asked what should be the default container panel, grid was the choice based on that fact.
Cory
I have a WPF User control that binds to a DataTable and generates CheckBox and a masked EditBox for each row in a DataTable. I have several instances of this control on my form. The total number of CheckBoxes to be generated is over 200. I am seeing some rendering performance issues. The form loads with all of the static controls ( Text Boxes, Drop Downs) instantly, then several seconds later the CheckBoxes appear.
Any thoughts?
Thanks
Unless all the 200 items are visible on the screen, you should be using some kind of virtual layout that creates the visual tree only for the visible items. This will greatly improve your performance.
What is "generating" the checkboxes? You should be using an ItemsControl (or subclass) and binding the data that represents the checkboxes to it. Assuming you're doing that, then what you want to do is get that ItemsControl to use "virtualizing" by applying the VirtualizingStackPanel.IsVirtualizing property to the ItemsControl like so:
<ItemsControl VirtualizingStackPanel.IsVirtualizing="true" ... >
You might also want to turn on "container recycling" which will also help performance. This is also done with an attached property:
<ItemsControl VirtualizingStackPanel.VirtualizationMode="Recycling" ... >
Too many checkboxes surely cost a lot, if you look at templates of basic controls, they are also filled with lot of uielements.
I would suggest if you can divide your UI into Tabs or Accordins that will cause less visible items on one screen as well as it will help user navigate to items easily and faster as well.
VirtualizingStackPanel will help but if your binding isnt correct it may lead to unpredicted results.
Custom Control Template:
You can also create your own custom checkbox template with least UIElements, like simple rectangle filled with different color on IsChecked property trigger. This will eliminate few animations etc that can surely imporve your rendering performance. I believe CheckBox is least important when it comes to animating UI.
When you are sure that you will be using "Text" as content, then simply create template with rectangle to show filled/empty value and put TextBlock with template binding to Content.
Try to give fixed width/height to your checkbox, whenever you fix the height/width of your controls/containers, it becomes eaiser for layout manager to render them, rather then keep on calculating and adjusting items.