Is there a way to get Silverlight databound controls to load in the background to shorten load times during another part of application use? Specifically, I have a tab control containing a datagrid that is slow to load when there are large number of columns and rows. The performance hit occurs the first time I click the tab. Is there a way to force this load on a background thread when app first opens or something similar?
Not sure this is exactly relevant but I just resolved an issue I had where I was firing up a new grid (which was already loaded but not visible). In the process of making it visible I also assign the ItemSource of a datagrid inside which - via a converter - generates controls. What I found was that although the datagrid in silverlight typically only loads rows it needs to (based on visibility) in my case the code sequence to show the grid and bind was happening too quickly and because the grid wasn't yet shown it (silverlight) decided it needed to load all the rows.
Calling UpdateLayout() prior to generating the controls and binding resolved the issue.
Related
Background:
I use converters to acquire values for most of my binding statement because the bindings are so complicated that even multi-binding cannot satisfy. I have to calculate the value in the converters and return the value. Also I use OneWay or OneTime binding just to show the correct value. When user changes a value, I use Handlers to set the value. The Handlers are also complex program which cannot be simply replaced by TwoWay or OneWayToSource binding. Actually in this case the DataContext does not have any meaning. I use converters. Another reason of using converters is that all Controls are loaded dynamically using many DataTemplates and it's hard to create dynamic DataContext for each Controls in each DataTemplate.
With above background, my application works fine. I'm looking for solutions for our new problem below.
I have many group of Buttons each represent a warehouse containing different type of items.
When double-click a Button, a detail window pops up and user can modify the items. Those items can be represented by CheckBox, Combobox, TextBlocks, TextBox, etc.
For user's convenience, I duplicated some of the frequently-modified Controls from the popup window onto the Button itself (WPF allows Button to contain sub-controls), so that user can directly modify the items without double-click and popup the detail window.
Each Button could contain unknown number of sub-controls such as CheckBox, Combobox, TextBlocks, etc. Here "unknown" means that in the future developer can duplicate any controls onto the Button if the Controls for those items are deemed frequently-modified.
Everything works fine so far.
When user modifies an item in the popup window and closes the window, I used to reload the DataTemplate for the whole window so that everything is refreshed and the controls duplicated onto the Button can synch up with the value modified from inside the popup window.
Everything still works fine so far.
The problem happens when the application runs on machine with slow hardware, where performance is an issue. On a much slower machine, reloading the whole DataTemplate for the whole application that contains many Buttons is quite slow.
So I'm looking for ways to just refresh the Button that is double-clicked, not all Buttons. However, I searched a couple of days and could not find ideal solution of refreshing a WPF sub-tree.
I tried to travel the sub-tree of the Button to assign null to the DataContext property and then assign back the old DataContext, but the binding seems not triggered and the converters were not called.
I saw someone suggested to use something like below:
((ComboBox)sender).GetBindingExpression(ComboBox.ItemsSourceProperty)
.UpdateTarget();
That demands that I know the Control and its property that has bindings. I think I can do the same for all possible Controls and properties but it does not seem a future-proof solution.
Anybody knows an effective way of refreshing a WPF sub-tree without knowing what is in the sub-tree?
I am making a search app in wp7. Every record's data is bound to a user control. I have introduced an infinite loading instead giving page numbers. So when the number of instances of the UserControl is increased in the screen the transition from one page to another page (like the preview or settings pages) or coming back from that page to the current page is getting slower. I cannot change the design (infinite loading concept).
What are the ways to handle this scenario? How about changing the visibility of the controls? And reference or suggestion will be highly appreciated.
Note I tagged WPF and Silverlight because the binding happens the same way in them, expected those to have dealt with scenarios like these.
EDIT Check this question, which is asked by me. Because of having UserControl's in the listbox the vertical offset is not being maintained. So I had no option other than using ItemsControl with scrollViewer around it. ItemsControl contains a list of 5 - 6 usercontrols which intern have itemsControls inside them, I thought virtualization may not happen in such cases. Am I right?
In WPF, this is done by Virtualization
Using Virtualization, only one copy (or a few copies) of the UserControl actually gets created, and switching to another user control actually just swaps out the DataContext that the control is bound to. It doesn't actually create a new UserControl.
For example, if you have an VirtualizingStackPanel with 100,000 items, and only 10 are visible at a time, it will only render about 14 items (extra items for a scroll buffer). When you scroll, the DataContext behind those 14 controls gets changed, but the actual controls themselves will never get replaced. In contrast, a regular StackPanel would actually render 100,000 items when it gets loaded, which would dramatically decrease the performance of your application.
This question about Virtualizing an ItemsControl can probably get you going in the right direction.
Take a look at this post, I believe the solution provided by Rico is what you are looking for. :)
I am creating a resource-intensive dashboard application that will have many areas of data visualization. I am thinking that it would be best to use a frame and load the pages needed one at a time using WPF pages. These pages will also have different data contexts, security restrictions, etc. But, another developer says I can accomplish the same thing using a TabControl.
Does a TabControl load all the items in all the tabs at once, on application startup? Or, can I load them lazily as needed like with WPF pages (page only loads content when navigated to)? Also, can you have different data contexts per each item in a TabControl?
In WPF you can use UI Virtualization which means that only the visible controls are initialized and rendered. As far as I know, the TabControl does not support UI Virtualization by default but maybe you can add it manually or use another control. Maybe you want to have a look at the following article which presents some performance tips. There is also mentioned that there is a difference between UI and Data Virtualization. Not showing the controls does not mean that the underlying data are not in memory. All your binding targets will be loaded, but the controls will not be rendered.
To your second question: Yes, every TabItem can have its own DataContext. If you use a TabControls ItemsSource to bind a list of items, the DataContext for every TabItem will be one item of the list. If you manually add TabItems, you can set the DataContext like that:
<TabControl>
<TabItem DataContext="{Binding Context1}" />
<TabItem DataContext="{Binding Context2}" />
</TabControl>
It is more complex than you would guess. If you bind to Tab Collection (think MVVM) then the tab only get created when it is selected. And with a Collection if you leave a tab and come back it gets built AGAIN. If you create the tabs in XAML then the tabs are all built when the windows loads. Yes you can have different DataContext for each tab. What I do for lazy loads is bind to the TabItem property IsSelected and if it is false all the Properties in the class just return a (fast) static type compliant value. If IsSelected is changed to true then I load the real values and call NotifyPropertyChanged (and I save the real values).
I use the heck out of this were I load a big objects and one tab is a summary. Tabs do not virtualize but if you have big lists then for sure use virtualization in the tab. You can use BackgroundWorker to create properites but once it returns and you bind that returned value the UI locked until the UI control is rendered. For me reuse of a single frame versus tabs is a UI thing. Just to break up code I typically load a tab with a frame and a page (and I typically pass data to the page in the ctor to load dynamic content).
I have the following components in a WPF application:
(1) Window
(2) ContentPresenter in the Window that is bound to a property in the underlying ViewModel. This Property references another ViewModel.
(3) A DataTemplate for the ViewModel that will be bound to the ContentPresenter referenced above. This data template instantiates a third-party grid that displays some data.
Whenever the ContentPresenter renders the data from the DataTemplate, it takes approximately three to four seconds for the UI to render. This causes the UI to hang for the duration of the time that it takes to render the content. Since I have little to no control over how the third-party control renders itself - my question involves whether or not it is possible to render content in a way that the UI will not hang.
Please advise.
Thanks.
Chris
How many rows is the grid displaying? And how many of those rows are visible on screen?
I'm asking because it's possible that you've got a UI layout that defeats virtualization. Usually, controls that show a scrollable list of data will perform virtualization. (The built-in ListBox does this, and any 3rd party grid of tolerable quality should do the same.) This is critical for performance, because it means your UI only needs to instantiate those items that are actually visible, rather than everything in your list.
But it's relatively easy to defeat this virtualization by accident. One way is to wrap the list or grid control in a ScrollViewer. You need virtualizing controls to be able to manage their own scrolling for virtualization to work, so the scrolling needs to happen on the inside. Wrapping a control in a ScrollViewer prevents it from doing its own scrolling. Another way it can go wrong is if you plug in a different ItemsPanel. A third possibility is that your list/grid control actually needs to be told to use virtualization.
But if you're using a control that simply takes a long time to render just the stuff you need to show on screen, then there's not much you can do - you'd need to contact the control vendor, or consider using a different vendor...
I'm using an IValueConverter in conjunction with DataTriggers (all in code, not XAML) to implement conditional styling for a WPF DataGrid (from codeplex.com). I have all the code in place, but when I update the styling (after obtaining some values from form elements) the datagrid does not update the display of the elements. I have to manually call this.dataGrid.InvalidateVisual() and then scroll down and back up to get the grid elements to refresh themselves. Is there a better way of doing things ?
I've tried using this.dataGrid.Items.Refresh(), but this causes a rebinding of the grid data (of which there may be thousands of rows) which in turn causes a huge jump in my program's memory consumption. Does anybody have any idea how to manually force a redrawing of the WPF data grid ? I've also tried doing this.dataGrid.Dispatcher.Invoke((Action)(() => {})); to try to force the dispatcher to perform an operation that will result in a redraw, but to no effect. Any suggestions are appreciated.