Silverlight scaletransform adjust scrollbars - silverlight

I have the following UI element hierarchy: UserControl>ScrollViewer>Canvas. I am drawing lots of stuff on the canvas, and it becomes larger than the UserControl, at which point the ScrollViewer displays the scrollbars. So far, so good. Now I apply a ScaleTransform to the Canvas (say, 2.0, making everything twice as large). However, my scrollbars to not adjust, so I can now only scroll half-way across my enlarged canvas. How do I get my ScrollViewer scrollbars to adjust when I apply a scaletransform to the canvas being displayed within the ScrollViewer?

Your problem is that the ScaleTransform is a RenderTransform and not a LayoutTransform. The size it reports to the ScrollViewer is the same size regardless of what the scale is.
One solution I've used in the past to get around this is to nest the Canvas in another Canvas. You can then in code change the size of the outer Canvas to reflect the actual dimensions of the inner Canvas. The ScrollViewer will then update to reflect the correct dimensions. You don't actually change the size of the inner Canvas, you just change the scale.

This answer should answer your question:
XAML: make a ScrollViewer show scrollbars when the ScaleTransform of a child object gets big

Related

Include Adorner in ScrollViewer scrollable region

I currently have an Adorner inside a ScrollViewer. Objects at the bottom of the scrollviewer can sometimes display a large adorner below them. Unfortunately, that adorner is not included in the ExtentHeight of the scrollviewer, so the lower portion of the adorner is clipped by the bottom of the scrollviewer's viewport.
Is there a way to get the adorner layer's contents to be included in the scrollable region of the scrollviewer?
I'm afraid the consensus from other sources and hours of investigation seems to be that what I mentioned simply isn't possible. My solution has been simply to detect the last item in my ListBox and automatically add a margin to its bottom when my Adorner is being displayed. It's a bit of a hack, but it achieves the desired behavior mentioned above.

Silverlight canvas scrollbars

I have read that placing a canvas inside a scrollviewer won't work because the canvas does not report its size. I have been experimenting with different containers (borders, grids, canvases and scrollviewers) and could really do with a simple explanation of how scrollviewers behave within nested containers. e.g. If I have a container hierarchy of UserControl>Grid1>Canvas1>ScrollViewer>Grid2>Canvas2 should scrollbars appear around Grid2 when Canvas2 becomes wider than Canvas1? (or indeed wider than UserControl) If not, how should I organise my containers so I can add loads of uielements to Canvas2 and have scrollbars appear as necessary. (My usercontrol width and height are set to 100%)
Canvas will work with a ScrollViewer if you explicitly give it a size. The problem comes from the fact that if you don't supply a Height and Width for any control it will try and determine it's available area based off it's parent container. A ScrollViewer however has infinite available area.
Take a Grid for example. If I define a Grid that has 2 Star Width columns and 2 Star Height rows. How does the Grid know how wide each of those columns should be? The star says they should be half of the available area, but inside a ScrollViewer the available area is infinity.
What controls are you adding to Canvas2? If you are adding them with fixed positions than the ScrollViewer will expand to house all elements. If you aren't giving them fixed positions than all the controls will stack on top of each other, because that is the arrange behavior of a Canvas

WPF Adorner Transforms

I am building a control, where the user can "draw" resizable rectangles that are laid over the content. To resize those rectangles, I use an Adorner on top of them which contains 4 Thumbs to change the size of the rectangle.
The problem is, that this control is is "zoomable", meaning a ScaleTransform is applied to the whole control depending on a zoom factor. The Thumbs in the Adorner are affected by this ScaleTransform as well.
But I need them to keep their size, independent of the zoom factor.
I tried putting the Adorners in a Layer of another non-transformed control instead of the rectangle-layer, but this didn't work.
How can I achieve this?
Thanks,
Andrej
Have you checked this post: Transformations on AdornedElement are also applied to Adorner?! ? Does it work?
I also find this question on MSDN: How to exclude scaleTransform from GeneralTransform in Adorner GetDesiredTransform method., this is good because also there is some example code.

WPF Adorner Clipping

I have an ItemsControl in a ScrollViewer. The items in the ItemsControl are expanded to a DataTemplate which basically consists of an Adorner.
Now the problem is, when scrolling, the Visual Children of the Adorner are visible outside the ScrollViewer. Lets say I scroll from the Horizontal Offset 0 to 100, the Visual Children of the Adorner move to the left and are visible next to the ScrollViewer, although they should be hidden. Setting ClipToBounds on the ItemsControl or the ScrollViewer does not work.
I understand, that Adorner are rendered above all elements z-order wise, but they really shouldn't be visible in such cases as with the ScrollViewer. The adorned Element by the way behaves like expected and is not visible through the ScrollViewer.
Is there any easy way to "clip" the Adorners, so that they are only visible in the visible scroll area?
Thanks,
Andrej
Setting ClipToBounds on the containing control is not enough. You must set the adorner's IsClipEnabled property too.
I've encountered the same problem when subclassing the WPFToolkit DataGrid to draw an adorner around the current cell.
The content of the ScrollViewer is rendered by a ScrollContentPresenter instance. ScrollContentPresenter has its own adorner layer, which is accessible through the ScrollContentPresenter.AdornerLayer property.
I found that my adorner correctly clips if I add it to that layer.
My solution was to push a clip region onto the drawing context, render whatever I needed, and pop the clipping at the end, like this:
drawingContext.PushClip(new RectangleGeometry(new Rect(0, 0, this.AdornedElement.RenderSize.Width, this.AdornedElement.RenderSize.Height)));
// continue drawing
drawingContext.Pop();
You can plug this in into any Adorner, the bounds are already available as part of the element.

Is there a way to automagically make a canvas scroll on overflow in WPF?

Been checking the web and this site, but couldn't come up with any descent results.
Is there a way to make a canvas in WPF show scrollbars on overflow ? Been trying the scrollviewer, but can't get it to work :(
Thanks in advance..
The problem you're running into is that Canvas, unlike many WPF panels and containers, does not size to contents. That means if you add an element which goes outside the canvas boundaries it will not update it's size. Hence embedding a Canvas in a ScrollViewer will do no good unless you manually update the size of the Canvas.
It sounds like what you want is a Canvas which supports size to contents. This blog entry has exactly that control.
http://themechanicalbride.blogspot.com/2008/11/auto-sizing-canvas-for-silverlight-and.html
I took a different approach and abandoned the Canvas for Grid. The Canvas is more performant but for my purposes at least I haven't noticed a difference. The grid can mimic the behavior of canvas by doing the following.
Create a single row,single column grid.
Set the HorizontalAlignment to Left
Set the VerticalAlignment to Top
Use Margin "x,y,0,0" to set the position.
Bam..works just like canvas and it works great in a Scrollviewer.

Resources