We are facing an issue, wherein we need to suspend grid painting for some time. We are using devexpress DXGrid bound to XPInstantFeedbacksource. We have a requirement of refreshing source every 2-3 seconds to get the updated realtime data which is huge (around 40 -50 thousand records in a day).
However the refresh method of the above mentioned source binds the grid asynchronously and when it does so, it causes some kind of flickering onto grid. Internally it captures layout of grid before refresh and renders it back in postrefresh phase.
I have tried many things like wrapping the refresh call in bigindataupdate and enddataupdate, but it doesn't seem to work.
However, one thing which looks interesting to me is using Win32 api to suspend layout painting for some moments and resuming it.
I found something at
How do I suspend painting for a control and its children?
which works well for Winforms, but in WPF as far as I know, individual controls share window handle. And method call
SendMessage(parent.Handle, WM_SETREDRAW, false, 0);
uses control handle to interact with WIN32. Also, I observed that if I suspend layout for window underlying grid still gets painted which is strange to me.
I just want to know , if I am going in right direction by suspending grid layout to avoid flickering and if yes please suggest some way to achieve this.
Thanks,
Gurpreet
Related
I'm overriding WPF's OnRender to draw complex graphics. This may rarely take a long time. I would like to indicate to the user that the app did not crash, but is "merely" taking a long time to render.
How would I do that? It seems not possible to modify the UI in any way during the OnRender call.
You are talking about placing a "Busy Indicator" on top of your drawing.
Just place a half transparent grid on top with the writing "Loading..."
and you're done.
Bind its visibility to some bool that you update once when entering the complex rendering, and once when finished.
Or put a spinning Ellipse with gradient background if you want to see motion..
Since the OnRender method will execute on the UI thread you cannot do anything else such as displaying an interactive ProgressBar or respond to user input during the execution of your code.
What you can do is to pop up a new window that launches in a separate thread and display this one right before you begin to draw your complex graphics.
Please refer to my answer in the following similar question for more information about this.
Wait screen during rendering UIElement in WPF
Once the OnRender method has returned you then close the temporary "loading" window:
Can I stop WPF from executing UI actions out of the order in my code
The title sounds like some easy well-known problem, but please check out this:
I've got some WPF window that handles a list of Threads and shows ProgressBar for each Thread. The invoked GUI refresh is working for most threads showing right number of percent and also for unknown progress the IsIndeterminate state is animated. After the thread is done some animation fades out the ProgressBar.
However, for some of my heavy tasks the ProgressBar is not visually updated. For example, the IsIndeterminate state refreshes only if I force the GUI to redraw by some mouseover events or by moving the form. The fade out animation shows the same problem.
I think this is no usual stucking because the UI thread is not blocked by further operations (there's only one invoke setting IsIndeterminate = true). Until now, I wasn't able to find out what's the different between heavy tasks that result in this behavoir and tasks that do not.
Please notice that the replacement of the Thread by a BackgroundWorker shows exactly the same problem (I'm also not sure why people say BackgroundWorker will not freeze the GUI but Threads allegedly do - this seems not entirely right). Please also notice that although the thread is paused by Thread.Suspend() (yes, I know it's obsolete but this is an essential feature I need, since the task content is unknown) the GUI will not show up the IsIndeterminate animation if no other GUI element forces the refresh of the window.
Any ideas what that problem might be and how to fix it? I just need the usual refreshing rate for drawing animated controls...
I am using the normal WPF DataGrid to display some data from a REST feed. The REST feed is paged with a next link that contains the URL for the next set of items. The DataGrid is virtualised by having a custom object that implements the IList interface (not IList), and knows how to fetch missing data from the REST feed.
The issue is that if a user scrolls immediately to the bottom this component must do a bunch of REST requests for each "next" page, causing the GUI to freeze. Of course I could simply put up a "wait" screen, but I would actually be able to show an accurate progress bar.
So to accomplish this I have a progress bar on my application status bar that has visibility set to IsLoading on the data context, which in turn passes this down to the paging object. There is another property LoadedPercentage which shows how much of the required data has been loaded.
The issue is that when I scroll to the end of the screen, it still freezes and shows nothing. I set breakpoints in the code to see if my properties were being accessed and they were all hit at the correct times and showed the correct values. So I deduce from this that the DataGrid itself is somehow stopping the GUI thread from doing any drawing while it waits for the IList object to return the requested object.
So does anyone know of a solution for getting the status bar to show up? I would really rather have the status bar appear and track progress rather than some "loading please wait" screen. Can this be done at all with the built in objects or do we have to purchase some third party grid?
EDIT: It wasn't completely clear to some so I wanted to mention: I am doing virtualisation as described here among other places. It seems that when the DataGrid requests a specific entry it blocks the entire UI painting until it the request completes.
Well, UI is busy fetching data from the REST service. If you don't like the behaviour, you can implement data virtualization.
This post explains more: WPF Datagrid: Lazy Loading / Inifinite scroll
As far I know, there is no "ready" solution in WPF, and it will be little hassle, but it should work with some tweaking.
Implementing your custom IList doesn't sound like it would work, so I am not sure about how to "fix" your solution, and if it's even possible.
I have a grid control that is trying to display large amounts of data and so it takes a long time to render on the UI thread.
I have added a loading bar that animates and displays depending on if the screen is busy or not (is rendering).
However the loading bar is just freezing when the grid is trying to render. I am assuming this is because there is only one UI thread and that thread it busy.
Does anyone know a way in which I can keep the loading bar animated?
Many thanks,
Matt
You need to process the enumeration or data fetching from UI rendering, do the processing part for get the data ready for UI rendering on separate thread.
http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx
If you insist on the grid rendering all the data at once, it all depends on whether the grid's rendering code can "yield" or not, kind of like the old Windows Forms "DoEvents()" method. It sounds like it's implemented in such a way that it doesn't, in fact, yield processing back to the UI thread during its rendering, and hence your progress bar never gets updated.
Does the grid ever call into your own code while it's rendering its content? If so, you could use those instances to update the state of the progress bar.
Have you looked into virtualizing the contents of the grid? You can get UI virtualization basically for free if you wrap the FrameworkElements that you need rendered in a VirtualizingStackPanel. If you want somewhat more complexity, you can also get data virtualization by wrapping your dataset with a PagedCollectionView class, and then writing . See here for more details. See also here for another (simpler?) way of implementing the same sort of virtualization.
My app has many controls on its surface, and more are added dynamically at runtime.
Although i am using tabs to limit the number of controls shown, and double-buffering too, it still flickers and stutters when it has to redraw (resize, maximize, etc).
What are your tips and tricks to improve WinForms app performance?
I know of two things you can do but they don't always apply to all situations.
You're going to get better performance if you're using absolute positioning for each control (myNewlyCreatedButton.Location.X/Y) as opposed to using a flow layout panel or a table layout panel. WinForms has to do a lot less math trying to figure out where controls should be placed.
If there is a single operation in which you're adding/removing/modifying a lot of controls, call "SuspendLayout()" on the container of the affected controls (whether it is a panel or the whole form), and when you're done with your work call "ResumeLayout()" on the same panel. If you don't, the form will have to do a layout pass each and every time you add/remove/modify a control, which cost a lot more time. see: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.suspendlayout(VS.80).aspx
Although, I'm not sure how these approaches could apply when resizing a window.
Although more general than some of the other tips, here is mine:
When using a large number of "items", try to avoid creating a control for each one of them, rather reuse the controls. For example if you have 10 000 items, each corresponding to a button, it is very easy to (programatically) create a 10 000 buttons and wire up their event handlers, such that when you enter in the event handler, you know exactly which element you must work on. However it is much more efficient if you create, lets say, 500 buttons (because you know that only 500 buttons will be visible on the screen at any one time) and introduce a "mapping layer" between the buttons and the items, which dynamically reassigns the buttons to different items every time the user does something which would result in changing the set of buttons which should be visible (like moving a scrollbar for example).
Although, I'm not sure how these approaches could apply when resizing a window.
Handle the ResizeBegin and ResizeEnd events to call SuspendLayout() and ResumeLayout(). These events are only on the System.Windows.Form class (although I wish they were also on Control).
Are you making good use of SuspendLayout() and ResumeLayout()?
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.suspendlayout(VS.80).aspx