Prevent redraw of window when resizing grid row/column - wpf

WPF grid container, with multiple rows/columns with usercontrols loaded in the sections.
Some rows/columns are expanded/collapsed by setting the Column/Row width (from 0 to 125* or a fixed value), based upon a button click.
Simple example code:
If colgrdFolder1.Width.Value Then
Me.Width = Me.Width - colgrdFolder1.ActualHeight
colgrdFolder1.Width = New GridLength(0)
Else
Me.Width = Me.Width + 150
colgrdFolder1.Width = New GridLength(150)
End If
This works, but when the parent resizes, it flashes as the column/row is set. When the parent Width is first increased you can see the grid resize and then when the new colWidth is set, it resizes (and flashes) again.
Is there not a property/method to freeze the window/prevent redraws until the resize is complete?

I think there are BeginInit() and EndInit() methods, that should do what you want (prevent redraw), but in my experience they haven't really worked (maybe I have used them incorrectly).
I don't know of any other way of preventing redraw, perhaps someone who is more of an expert in WPF can shed some more light...

Related

Resizing elementhost is causing flickering

I use an ElementHost control to integrate Wpf into a winforms application. I have created a "kind" of step by step set of screens similar to a wizard with next and back buttons among others.
Windows Form ---- ElementHost ---- Wpf
When I go through the different screens, i am not closing and opening a new window again, instead I simply keep the same window already opened and I change only its content. The problem of this is that the elementHost is not resizing to fit its content height, neither if the content height is decreased or increased (caused by for example an expander collapse or expand or some other control). Instead the elementhost keeps always the height that was taken the first time it was open.
The elementhost has set its properties correctly, AutoSize = true and Dock to Fill. And the Windows Form where the elementhost is, also has AutoSize set to true correctly.
So in order elementhost resizes, what I do is to "force" the elementhost to resize by doing the following on each transition between screens:
System.Drawing.Size eh = myElementHost.Size;
ElementHost.SuspendLayout();
ElementHost.AutoSize = false;
ElementHost.Size = new System.Drawing.Size(eh.Width, eh.Height);
ElementHost.AutoSize = true;
ElementHost.ResumeLayout(true);
This trick causes elementhost to resize to fit its content height but.... it is causing flickering.... also for example, each time I click on the toggle button of an expander to collapse or expand it or do something in the content that cause it to modify the content height, I need to call above piece of code to force elementhost to resize correctly to fit its content height but again, it is causing flickering, so how can avoid flickering in this particular use case?

How to Set the Background of WPF Control and Ensure Rendering Immediately When Visible?

I have a WPF application that takes a screenshot of the contents of a WindowsFormsHost control and applies it to the background of a Grid control. The Grid acts as a transition screen from the WindowsFormsHost to other WPF controls. This is done to make a smooth transition effect and to avoid air space issues. I first capture the WinFormsHost control image as a bitmap and apply it to the Grid background. Then programmatically change the visibility of the transition Grid to visible. Then do an opacity animation to smoothly show another control. It works perfectly about 70 to 90 percent of the time depending on what computer I test the application on. The problem is that the transition Grid background is not being rendered fast enough or at the correct time. So that occasionally I am seeing a screenshot from a previous transition which does not match the current screen image at transition time.
If I could somehow ensure that the transition image was drawn before the Grid is made visible, it would work everytime. I just cannot see how to do this. The application seems to always wait until the last minute to do any rendering.
I have tried to force rendering with Dispatcher.Invoke() and Dispatcher.BeginInvoke() methods. I have also tried to delay the time when the Grid is made visible with a Dispatcher Timer, but no matter how much time there is between the call setting the background image and setting the visibility, the Grid does not always update. I have also tried things like InvalidateVisual() with no luck.
After looking at many examples into problems involving WPF's rending and UI threads, I made several attempts to correct the problem...
Attempt 1 - Works poorly, but attempt works better with a line of code that first sets background to nothing or black:
TransitionScreen.Visibility = Visibility.Visible
TransitionScreen.Background = Nothing
TransitionScreen.Background = New ImageBrush(BitmapToImageSource(GrabScreenshot(ScreenWidth, ScreenHeight)))
State = "WPFControlMode"
SwitchState()
Attempt 2 - Best results so far. Works fair to well depending on computer. Increasing the counter value does not improve results. The appearance of the TransitionScreen will be delayed with a larger counter value, but will have the same chance of showing a previous screenshot (about 1 in 5 times on my laptop):
Case "Transition"
'Grab Screen Shot and apply to transition screen...'
TransitionScreen.Visibility = Visibility.Visible
TransitionScreen.Background = Nothing
TransitionScreen.Background = New ImageBrush(BitmapToImageSource(GrabScreenshot(ScreenWidth, ScreenHeight)))
End Select
'The following code is inside a loop...'
If State = "Transition" Then
TransitionCounter += 1
If TransitionCounter = 25 Then
TransitionCounter = 0
TransitionScreen.Visibility = Visibility.Visible
TransitionScreen.Background = Nothing
TransitionScreen.Background = New ImageBrush(BitmapToImageSource(GrabScreenshot(ScreenWidth, ScreenHeight)))
State = "WPFControlMode"
SwitchState()
End If
End If
Attempt 3, 4, 5, ... - Attempts try to force rendering of control by working through Dispatcher. These attempts do not appear to help and often make the problem worse. They have been used in combination with both attempts 1 and 2.
Case "Transition"
'Grab Screen Shot and apply to transition screen...'
TransitionScreen.Visibility = Visibility.Visible
TransitionScreen.Background = Nothing
TransitionScreen.Background = New ImageBrush(BitmapToImageSource(GrabScreenshot(ScreenWidth, ScreenHeight)))
FlushWindowsMessageQueue()
End Select
'Tried many variations of the following procedure. Every dispatcher priority with both BeginInvoke and Invoke methods, as well as calling the methods through Application and TransitionScreen objects.'
Private Sub FlushWindowsMessageQueue()
Application.Current.Dispatcher.Invoke( _
New Action(AddressOf DummySub), _
DispatcherPriority.Background, _
New Object() {})
End Sub
Private Sub DummySub()
End Sub
There were more attempts also, but this should give you an idea of what I have tried. This is a real puzzle. This is the last major problem with a fairly involved project, and I am pretty much invested in the transition screen at this point. If you can think of anything, I will greatly appreciate it. Thanks.
I did come up with a work around for this problem. I do a transition animation before I take the screenshot. The transition animation results in a lower resolution image than the control would normally show. Then I take the screenshot of the lower resolution image which can be applied to the transition grid control, after it is made visible, fast enough that there is never a flicker. Then when I want to return to the WinFormsHost control, I run through this process in reverse. My application now works without flicker and run smoothly on most computers I have tried. On some computers with large monitors, there is sometimes a slight delay when rendering the transition screen, but still no flicker. The delay is about half a second, and I assume it has to do with the larger area that transition image must be rendered to.
Also, the above was done in combination with method/attempt #2. The flicker still occurs when in combination with attempt #1.

Silverlight child window getting cropped from edges when resizing browser window

I am using ordinary Silverlight ChildWindow in my application. When resizing the browser window, in particular when making its width smaller than that of the child window, the edges of the child window get cropped, so that it is impossible to close it via the close button as it is no more visible. I have tried a number of workarounds but nothing helped. In particular I have subscribed to the SizeChanged event of the child window and set its sizes relative to the layout root's sizes. Here is the code of the SizeChanged event handler:
// Get the dimensions of the application screen
Size appSize = Application.Current.RootVisual.RenderSize;
// Make the child window occupy the 90% of width and 40% of height of the entire screen
this.Width = appSize.Width * 9 / 10;
this.Height = appSize.Height * 4 / 10;
This code modifies the sizes of the child window, but it also updates the sizes of the overlay, so that it no longer covers the whole page, which is a very strange behavior.
Has anyone encountered this kind of problems? Please share any ideas.
Thanks in advance.
I had a similar problem. It occured because scale in a browser was higher than 100%.

how to get height width of a stackpanel (with invisible scrolled area)

i am trying to take a snapshot of my screen in a wpf application. everything works fine, but the only problem is that, when i need to take the screenshot of the contents of a stakpanel which have some hidden contents in a scrollviewer's scrolled area, my code only takes a snaphsot of the visible part of stackpanel. plz take a look below...
RenderTargetBitmap renderBitmap =
new RenderTargetBitmap(
(int)spMain.ActualWidth,
(int)spMain.ActualHeight,
70d,
70d,
PixelFormats.Pbgra32);
ActualWidth/ActualHeight properties only provide the height/width of the visible part.
Q- how can i get a snapshot of the complete stackpanel?
thanks
I solved the issue by measuring and arranging the UI Element before taking the snapshot.
spMain.Measure(new Size(spMain.ActualWidth, spMain.ActualHeight));
spMain.Arrange(new Rect(new Size(spMain.ActualWidth, spMain.ActualHeight)));
:)

WPF PreferredSize property?

In Windows Forms, you have a PreferredSize property that will tell you how large a control would like to be.
Where's that property in WPF?
I have a Grid with some content (of unknown size) and would like to create an animation that increases the grid in height from 0 up to its preferred (auto) height. Of course the grid is either at 0 height or collapsed at the beginning, because it's not supposed to pop up in an instant but smoothly "fade in". So I cannot use the ActualHeight property for the animation target because it is always 0. The opposite direction animation should be easier because I can animate from ActualHeight (or just no explicit start value) to 0.
Given a FrameworkElement (element) and I wish to allow it to expand fully and then measure it's size I do the following:
element.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
element.Arrange(new Rect(new Point(0, 0), element.DesiredSize));
element.UpdateLayout();
Size sizeElementWantsToBe = element.DesiredSize;
Caveat: I found this question because I'm having problems with this method of triggering layout with Telerik RadGridViews with templated columns. But I doubt you will have that problem.
Hope this helps.

Resources