How to make WPF scrollviewer smoother - wpf

I'm using a scrollviewer like this:
<ScrollViewer PanningMode="Both" >
<TextBlock FontSize="15" TextWrapping="Wrap">
(a block of random text)
</TextBlock>
</ScrollViewer>
I am using a very decent new laptop with a touchscreen but if I flick the text, the movement is not nice, it is jerky. If I use any windows 8 apps with touching / flicking etc the movement is silky smooth.
Is this an issue with WPF? Is there any way to get smooth scrolling?
Thanks

Ensure that ScrollViewer.CanContentScroll is set to false.
<ScrollViewer PanningMode="Both" CanContentScroll=false>
<TextBlock FontSize="15" TextWrapping="Wrap">
(a block of random text)
</TextBlock>
</ScrollViewer>
Physical vs. Logical Scrolling
Physical scrolling is used to scroll content by a predetermined
physical increment, typically by a value that is declared in pixels.
Logical scrolling is used to scroll to the next item in the logical
tree. Physical scrolling is the default scroll behavior for most Panel
elements. WPF supports both types of scrolling.
http://msdn.microsoft.com/en-us/library/system.windows.controls.scrollviewer.cancontentscroll%28v=vs.110%29.aspx
Alternatively, you could try this fella:
SurfaceScrollViewer Class
Users can flick the content of a SurfaceScrollViewer control by
touching the control, rapidly moving their finger a short distance,
and then lifting their finger. When their finger is lifted, the
content of the SurfaceScrollViewer control continues to move. The
content then decelerates and comes to a stop. You can programmatically
stop the movement caused by flicking by calling the StopFlick method.
You can manipulate the content of a SurfaceScrollViewer either by
moving a scroll bar (like with the WPF SurfaceScrollViewer) or by
direct touch interaction with the content itself. The ability to
manipulate the content directly is called panning. By default, panning
is enabled. You can disable it by setting the IsManipulationEnabled
property to false.
http://msdn.microsoft.com/en-us/library/microsoft.surface.presentation.controls.surfacescrollviewer.aspx
(Archived link)

Related

Maintain position for child in a Canvas with zoom and scroll - WPF

I would like to implement the following functionality.
I have a canvas with several UIElements inside it. The Canvas allows to zoom and scroll applying a scale and translate transforms.
I would like to maintain the red square always in the same position (left bottom corner of the Canvas), to behave as a floating control, so as I change the zoom or the scroll, the red square always maintains it's size and position. Something similar to google maps "Earth window":
What is the best approach to implement it?
NOTE: I tried to use the WPF adorner layer but it does not respond to mouse events, and I need to interact with the red square.
As Clemens said, put it in another layer on top. Grid can host multiple items in the same cell, so create a 1 by 1 Grid for your Canvas add content on top just like any other WPF layout. The later items appear on top (unless Z layer is specified):
<Grid>
<Canvas>
... do all my fancy drawing
</Canvas>
<Rectangle VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="100" Height="100" />
</Grid>
Note, you may have trouble if the canvas has any non WPF rendering, such as video or embedded WindowsForms content. I've seen people have trouble with drawing WPF stuff on top of that.
I also believe you can set Canvas.Bottom="20" to set the position relative to the bottom edge, but I've never used it.

Scrollviewer & Canvas

I am trying to load an image within a canvas such that, if the size of image overflows the canvas, the scroll bars should get activated (MS Paint style)
<Window>
<ScrollViewer>
<Canvas ScrollViewer.HorizontalScrollBarVisibility="Visible"
ScrollViewer.VerticalScrollBarVisibility="Visible">
<Image Source="SampleImage.jpg" />
</Canvas>
</ScrollViewer>
</Window>
Now as Canvas is stretched to Window's size, scroll-bars won't appear as Canvas is not actually overflowing out of the Window.
Secondly, as the Image is much bigger than the Canvas, it is getting clipped at the bounds of Canvas, so ScrollViewer doesn't think that its content: Canvas is actually overflowing.
It happens a lot of time with StackPanels too, that even though the bound data has tens of rows, but still the scrollbars don't get activated. Sometimes scrollviewers appear as mystery to me.
So, what should be the basic logic kept in mind when using ScrollViewer control.
Thank you.
Edit: Just edited the question title, so that whosoever has problem with canvas can get this question easily in search.
From MSDN:
Canvas is the only panel element that has no inherent layout characteristics. A Canvas has default Height and Width properties of zero, unless it is the child of an element that automatically sizes its child elements. Child elements of a Canvas are never resized, they are just positioned at their designated coordinates. This provides flexibility for situations in which inherent sizing constraints or alignment are not needed or wanted. For cases in which you want child content to be automatically resized and aligned, it is usually best to use a Grid element.
Hovever, you can set Canvas Height and Width explicitely:
<ScrollViewer Height="100" Width="200">
<Canvas Height="400" Width="400">
//Content here
</Canvas>
</ScrollViewer>
Maybe one of these two Links might help you:
Silverlight Canvas on Scrollviewer not triggering
ScrollBars are not visible after changing positions of controls inside a Canvas

How can I prevent WPF from clipping my image?

I am writing a WPF app that displays an image that is initially centered. The user can zoom in/out and move the image, which are implemented using ScaleTransform and TranslateTransform. That works great.
The problem is when the image is significantly bigger than the window, and the user moves the image or zooms out enough so that the entire image should be visible. The portion of the image that was originally hidden isn't rendered, and instead only the originally viewable part of the image is drawn.
Based on some other questions, if I put my image inside of a Canvas that will cause the entire image to be rendered, and when moved it will be rendered correctly. The problem is that I don't want my image to be in a Canvas, since that prevents any other layout from occurring - the HorizontalAlignment and VerticalAlignment properties are ignored (so the image is no longer centered), and I need to implement an option that will draw the image as large as possible to fill the entire area of the window which no longer works (setting the Stretch property to UniformToFill doesn't do anything).
Currently the two transforms are set to the RenderTransform property. If I use LayoutTransform instead, the entire image is drawn, but this also prevents the user from moving any portion of the image off the edge of the window (which is behavior that I would like to keep).
How can I tell WPF to always render the entire image without using a Canvas or a LayoutTransform?
I suggest not using a TranslateTransform but instead rely on the ScrollViewer.
<ScrollViewer>
<Grid>
<Image Source="blabla">
<Image.LayoutTransform>
<ScaleTransform />
</Image.LayoutTransform>
</Image>
</Grid>
</ScrollViewer>
The ScrollViewer gives the Image infinite space to expand, the entire image will be rendered. The Grid forces a centered layout while still allowing the image to expand. If you don't like the scrollbars to control the translate then you can hide them and roll your own solution.
LayoutTransform is definetely the way to go, so that the image's actual size in pixels (based on the zoom) is properly reflected onto your window.

Vertical scrolling in silverlight

I have a silverlight application that is set to use 100% browser height.
As I dynamically add controls to a canvas (which can be dragged around), I would like the expand the canvas vertically.
Ideally show the browser scrollbar so the user can move up or down, if that can't be done, use the scrollbar control. I would also need to handle the user changing the size of the browser. Any suggestions on how to do this ?
Cheers,
Just wrap your Canvas inside of a ScrollViewer as follows:
<ScrollViewer>
<Canvas>
...
</Canvas>
</ScrollViewer>
Jim McCurdy
Face to Face Software and YinYangMoney

Get Width Available for Children in a Scrollviewer

How do I get the width available for the children of a scroll viewer in XAML? Thanks.
There's no direct way of doing this that I know of, since WPF automatically passes the available space in to the child controls' Measure() function so that they size to fit the available space.
Note that, by default, it passes in infinity for the vertical direction, since content can scroll forever vertically. You can change the visibility of the scroll bars in both the vertical and horizontal direction to affect whether infinity is passed vertically, horizontally, or both.
The best way of figuring out how wide the child controls actually have to layout in pure XAML would be to create an empty control - for instance, an empty grid - and then bind to its ActualWidth property:
<ScrollViewer>
<StackPanel>
<Grid x:Name="MeasureGrid"/>
<TextBox Text="{Binding ElementName=MeasureGrid, Path=ActualWidth}"/>
</StackPanel>
</ScrollViewer>
Aside from displaying the width that is actually available to controls, I don't see any other use for this information in XAML, though - all of the other scenarios I can think of can use this information implicitly. Can you give us more information on what you are trying to accomplish?

Resources