I have an application to which I want to add a progress bar. It works in most cases. In one case the time is actually taken because of binding and layout work which is asynchronous, so my progress bar is hidden before the work is actually done. Its rather large list of items shown within a scroll view. I can't use virtualizing because I need it to scroll smoothly as it is a touch screen application. So needless to say, it takes forever to bind and layout this list. Is there any way I can get notified that the binding and layout has finished?
I'm using Visual Studio 2010, but because of constraints I'm forced to use .Net 3.5.
If you want to execute code when binding and rendering are completed, use this code.
Dispatcher.Invoke(new Action(() =>
{
// hide progress bar
}), DispatcherPriority.Input);
Related
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
Currently I am stuck with a problem that is simple on the first sight. Its about automated GUI testing.
I want to make a row/cell of a WPF DatGrid completely visible by scrolling using ScrollIntoView(row) and then accessing the row/cell directly after. Unfortunately scrolling in ScrollViewer seems to happen asynchronously. This means I need to wait for the scrolling to finish before accessing the row/cell. For this purpose I found the ScrollChanged event I can subscribe.
There is only one detail I can not solve: If the row/cell I want to access is already visible (and no scrolling is necessary) I do not get that event and the algorithm gets stuck. I was not able to find a reliable way to predict if a call to ScrollIntoView(row) actually scrolls.
Any idea how to solve this?
To make sure layout is updated call UIElement.UpdateLayout after you ScrollIntoView and before you want to use item. Quoting MSDN it
Ensures that all visual child elements of this element are properly updated for layout.
I have a .net 4.0 winforms project where I need to programmatically set the bounds (aka size) of a window (System.Windows.Forms.Form) and add/remove controls to/from it, at the same time, without visible flicker. The form is not user-resizable, the only place where its size is changed is the this.Bounds = foo / this.DesktopBounds = foo / ... call.
I already read about preventing flicker by sending WM_SETREDRAW using p/invoke, and about SuspendRedraw/SuspendLayout and friends. I still see flicker happening, and nailed the prob down to:
Windows redraws the form on setting its bounds/size, even if redraw was disabled.
I guess this is caused not by the form itself, but by the window manager somehow?
So - is there a way to absolutely prevent redrawing anything, in any circumstances, and then re-enabling redraw and refresh manually afterwards? Kind of "freeze window and display a snapshot", change stuff, and "replace snapshot with updated window (incl. position and size) in 1 go" ?
Thanks, cheers,
Tim
Use the ResizeRedraw property of the form. Set it to false.
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.resizeredraw.aspx
You'll also need to redraw the window manually after.
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.
I want to create a control which takes a while to create (Pivot) and then add it to the visual tree. To do this i would need to change the dispatcher of the control (and its heirachy) before adding it to the VisualTree.
Is this possible? Are there any implications of walking the controls trees and setting the _dispatcher field via reflection?
AFAIK this only works with Freezable derived classes. The best solution I see is to create the control on the UI Thread and show a progress bar during creation. To make this possible you will have to create the control in portions an let the progress bar update itself once in a while. This not only necessary for the progressbar but also will make sure that you application does not block.
Pseudocode (execure in extra thread):
this.Dispatcher.BeginInvoke(UpdateProgress(0));
this.Dispatcher.BeginInvoke(bigControlBuilder.Build(0,25));
this.Dispatcher.BeginInvoke(UpdateProgress(25));
this.Dispatcher.BeginInvoke(bigControlBuilder.Build(25,50));
this.Dispatcher.BeginInvoke(UpdateProgress(50));
this.Dispatcher.BeginInvoke(bigControlBuilder.Build(50,75));
this.Dispatcher.BeginInvoke(UpdateProgress(75));
this.Dispatcher.BeginInvoke(bigControlBuilder.Build(75,100));
this.Dispatcher.BeginInvoke(UpdateProgress(100));
this.Dispatcher.BeginInvoke(this.Children.Add(bigControlBuilder.GetControl()));
Update:
To make complex control more responsive you could also try UI-Virtualization/Data-Virtualisation:
Only load and show those visual items of the data items that are currently visible to ther user. Do not load and show visual items that are scrolled offscreen are to small to see or are in any other way invisible to the user. Upon userinteraction unload items that become invisble, load items that become visible.
To answer your question, I suppose it is possible to set _dispatcher using reflection but I would not recommend it at all. There is a deeply ingrained notion in WPF of thread affinity and STA so I wouldn't mess with that.
bitbonk's approach is a good one.
Another approach we have used in a project of ours was to create a second UI thread and have a progress indicator be rendered by the second UI thread while the first UI thread is building the UI. As long as the progress bar stays in the visual tree owned by the second UI thread, you should be good.