Scrollviewer & Canvas - wpf

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

Related

Flexible XAML-only layout. Is it possible?

I want to create resizable window wich will initially autosize to its content.
If the size of the window reaches some limits autosizing is disabled and growing controls are either clipped or shown with scrollbars.
Autosizing also must be off when user resizes the window.
The real task is to create convinient resizable dialog window with text control.
When it contains not much and not few text lines it is reasonable to initially autosize the dialog. The amount of text increases and dialog becomes larger. Sure it must have some size constraints.
P.S. I think it's quite a frequent task to define the layout where the guiding role of the sizing during measure pass of the layout conditionaly swithces from children to parent and back.
Share you ideas or existing solutions. May be I'm missing something.
Thank you.
Update 1
Let me explain the algorithm:
1) Window is shown (let's imagine all data/content is already set).
2) Its size is adjusted as if window's properties were:
MaxHeight = ...
MaxWidth = ...
SizeToContent = "WidthAndHeight"
3) User tries to resize the window. And he can do it. Inner controls change accordingly their size.
This behavior is equivalent to the properties set:
MaxWidth= "{x:Ststic Double.PositiveInfinity}"
MaxHeight = "{x:Ststic Double.PositiveInfinity}"
SizeToContent = "Manual"
ResizeMode = "CanResizeWithGrip"
Yes, you can do it with XAML only using animations/triggers but it's a little tricky.
Just hook into TextBlock Loaded event(xaml only) and change SizeToContent=manual && MaxWidth&MaxHeight=PosInfinity inside EventTrigger using animation.
Many of WPF's panels automatically resize based on their children. I'd recommend looking through this article to get an idea of what kind of layout panels are available in WPF: WPF Layouts: A Visual Quick Start
But to answer your question, place all your controls you want automatically sized in a panel that automatically stretches its children, such as a Grid or a DockPanel, and set the MaxHeight and MaxWidth properties of the panel to prevent it from growing past a certain height/width.
<Grid MaxHeight="100" MaxWidth="200">
<!-- Place your content here -->
</Grid>
Depending on the default behavior of the parent control containing your panel, you may need to set the HorizontalAlignment and VerticalAlignment to something other than Stretch too.
<Grid>
<Grid MaxHeight="100" MaxWidth="200" HorizontalAlignment="Left" VerticalAlignment="Top">
<!-- Place your content here -->
</Grid>
</Grid>
If you want a ScrollBar instead of clipping the content, add a ScrollViewer inside the Grid

Silverlight MultiscaleImage fill available height

I have a sample app with a MultiScaleImageControl. By default it fills the available ViewPort width. How can i make it use the available height?
Edit (Copy from comment)
It's nothing more than
<Grid x:Name="LayoutRoot" Background="White">
<MultiScaleImage HorizontalAlignment="Left" Name="multiScaleImage1" VerticalAlignment="Top" />
</Grid>
My question doesn't aim at the width of the control itself, but at the displayed MultiScaleImage...
I would recommend that you remove the VerticalAlignment property. In fact get rid of the HorizontalAlignment as well. This lets the containing grid size the control for you.
You may also be seeing the control simply maintaining the aspect ratio of the image. If the image is wider than its high then at zoom level 1 the image will not fill the entire height.

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?

Stretching a WPF Canvas Horizontally

How do I make a Canvas stretch fully horizontally with variable width? This is the parent Canvas, so it has no parents, only children.
XAML Source: it displays in blend
http://resopollution.com/xaml.txt
Use a Grid as the top level element in your UI - it'll stretch to fill its container. Then put a Canvas with HorizontalAlignment="Stretch" inside the Grid and it'll behave the way you want.
<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Canvas Background="Blue"/>
</Grid>
That worked for me. The key is your top level UI element. While a Grid fills all available space by default, Canvases take up only as much room as their contents demand.
I'm guessing you've tried
canvas.HorizontalAlignment = HorizontalAlignment.Stretch
If this doesn't work, then what you could do is bind the Width and Height properties of the canvas to the ActualWidth and ActualHeight properties of the containing window.
You could use a dock panel to get it to fill the available width. The last item in a dock panel list of controls is automatically stretched to fill the remaining space.
<DockPanel>
<Canvas />
</DockPanel>
The canvas should do this automatically, unless you are manually setting the height and/or width. What kind of control are you trying to place the canvas on? Can you post your code?
The problem is that you're specifying the Height and Width. Without these properties, the control may appear to vanish in the designer, but it should size appropriately when you insert the canvas into another control.
If I recall correctly, the next version of WPF will have 'DesignWidth' and 'DesignHeight' properties that allow you to show the control in the designer with a given size without effecting it's measurement when inserted into other controls.

Silverlight: Canvas overflows

I have created a Canvas, and within it I placed a StackPanel. The StackPanel is horizontal, and it accepts a list of thumbnailed images. The Canvas has a fixed size. When I put more thumbnails than the Canvas width can hold, the StackPanel is supposed to overflow from the Canvas, so I can move it to center the current thumbnail.
Everything works correctly, only, the StackPanel's overflow is visible! Is there a way to hide it? Or is the entire approach wrong?
Here is a screenshot. The canvas is the red box. The stackpanel is blue semi-transparent.
http://www.netpalantir.it/static/sl_canvas_overflows.jpg
Thanks!
Since the Canvas has fixed size, you can use clipping. Basically you have to do:
<Canvas Width="400" Height="300">
<Canvas.Clip>
<RectangleGeometry Rect="0, 0, 400, 300"/>
</Canvas.Clip>
<!-- your StackPanel here -->
</Canvas>
Here are few useful posts on the topic:
Clipping in Silverlight
Cropping or Clipping in Silverlight

Resources