MaxWidth and MaxHeight Expands Smaller Images Past Their Actuals - wpf

When using the Image control to load images on the wpf Canvas all works. But certain images are large and explode on the surface so I set the MaxHeight and MaxWidth to render those images within the max constraints.
Then the large image loading works, but the side effect is that the smaller than max size and width images are then Stretched to the largest size. This is due to the Stretch being set whose value is anything other than None.
<Image Source="{Binding Source}"
Stretch="UniformToFill"
MaxHeight="200"
MaxWidth="400"/>
Left image is w/o max's set. Right image is with maxes set
The Issue
Its apparent that I have competing priorities, on one hand later (after initial loading) the image can be resized and that resizing needs the Stretch set so it expands to that resize. The initial competing need as discussed is to load the images as is, unless they go over the max sizes
How can I achieve both based on need; on loading it resizes to max's only if greater than maxes? Then after the image load it can have the Stretch set to UniformToFill?
The Thing Tried
I tried to set the Stretch after the load, but it seemed to have the same effect. I am guessing it is fired not after the Image loads but unfortunately when the control loads; which happens before the image loads.
private void LoadedImage(object sender, RoutedEventArgs e)
{
if (sender is Image image)
image.Stretch = Stretch.UniformToFill;
}

Related

Translate a coordinate to maintain proportion when the canvas is resizing in WPF for VB.Net

I am making a Image manipulation tool in WPF (VB.Net)
I have implemented Image translation and zooming in Image control by using Image RenderTransform.
Actually, the Image is inside the Canvas control like a Photoshop Canvas.
And there is an Image within that Canvas control like a Layer in Photoshop.
What I want to do is when I resize the outer Canvas control, the Image inside should also be resized and repositioned as the outer control is.
It means, the Image should get 'new width, new height, new x(or offset-x or left), new y(or offset-y, or top)'
But so far as I know, surprisingly, RenderTransform does not actually change the Image location and size!
Which means, assume there is a photo of 10x20. If I enlarged the image twice then it looks like 20x40. But the properties of Width, ActualWidth, RenderedSize.Width all of them shows 10x20-the original size.
Moreover, although I pan(translate or relocate) the Image within the Canvas, the Left(or Canvas.Left) does not change at all!
In summary,
Image control within a Canvas control design
Move Image inside the Canvas with mouse - done by RenderTransform
Resize "Image(not Canvas)" inside the Canvas - performed by ScaleAtPrepend and RenderTransform too.
Resize the outer Canvas -> and it should encompasses the inside Image to be resized (like s to 1.5s in the figure) with the same
ratio of outer Canvas is, and the Left and Top (or offset x,y) of
the Image to be translated(or relocated) according to the proper
variable (like x,y to 1.5x,1.5y in the figure).
Unfortunately, using the zoom coefficient like '1.5' seems to be not viable because the original (x,y) point is alway (0,0) because the RenderTransform does not change the location values themselves.
Where can I start? How can I make it work?
Thank you in advance.
Here is a XAML design.
<Canvas x:Name="CanvasBoard" ClipToBounds="True" Background="#FFC1C1C1" >
<Image x:Name="CanvasImage" HorizontalAlignment="Left" VerticalAlignment="Top" MouseLeftButtonDown="MouseLeftButtonDown_Click" MouseMove="MouseMove_Click" MouseLeftButtonUp="MouseLeftButtonUp_Click" GotFocus="ImageGotFocus" />
</Canvas>
Panning with mouse core code.
Dim lsPoint = e.GetPosition(CanvasBorder)
Dim res As Point = lsPoint - firstPoint
Dim transform As MatrixTransform = CType(sender, Image).RenderTransform
Dim matrix = transform.Matrix
matrix.TranslatePrepend(res.X, res.Y)
CanvasImage.RenderTransform = New MatrixTransform(matrix)

[XAML-WP8.1]Grid View background image clip to bounds

I'm new on Windows development and more in Windows Phone Development.
I'm trying to create a grid view composed of three cell.
Each grid view are composed of one image (for the background) and a textblock.
My background image is a cloud image and I want the first image partialy hidden by the second one and the second one partially hidden by the third one.
I tried to play with the margin of the cell for the y part, that's works but my cloud image doesn't make the entire width of my cell. So I tried the "UnifirmToFill" option but my images are cropped...
On iOS development in this case we can use the magic property "ClipToBounds", everywhere I saw the answer "use the clip to bounds property" but apparently this property is a legend or Visual Studio lie me...
Do you have an idea to resolve my problem ?
Thank you in advance!
To resume:
If I use the "uniformToFill" stretch option, my image is zoomed. It is ok for me.
But there is a way to display the cropped part? I want my image zoomed and displayed out the cell view.
In XAML there are four possible Stretch options:
None
The image is shown in it's original size. If its larger than the parent element, it'll only show the top left portion of the image that fits inside. If the image is smaller than the parent element, then it's shown in it's entirety.
Fill
The image is resized to fill the parent element. If the aspect ratios are different, then the image will be stretched to fit the parent. This will distort the image.
Uniform
The image will be scaled up as large as it can be, while still being completely inside of the parent. Unlike Fill which will stretch the image to make it fit perfectly, Uniform will keep the aspect ratio of the image and stop scaling when it reaches the bounds of the parent.
UniformToFill
This is the bastard child of the previous two. It will scale the image, while keeping the aspect ratio, until it fills the parent element. This means that some parts of the image will be clipped if the aspect ratios are different.
For more information on the Stretch enumeration, hit it up on MSDN
UPDATE
If you want to show the image outside of the bounds of the parent you could do something like this:
<Grid Width="100" Height="50">
<Grid.Clip>
<RectangleGeometry Rect="0 0 100 50"/>
</Grid.Clip>
</Grid>
This was suggested here on SO

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.

stretchable histogram overlaying a picture

I'm in the process of making a WPF program that:
can scan a bitmap image, pixel-by-pixel, and assign it a data value (0-255)
design a class that allows panning and zooming of the picture
create a histogram, from the data values, that overlays the bitmap image.
I was able to do all three, however the issue that I am having is that the histogram doesn't dynamically (I think that's the word for it) stretch as I re-size the main window. Actually, nothing stretches to the correct size in the main window (the bitmap image just re-centers itself while keeping the same size). The histogram originally started as a transparent canvas that had many rectangle children. I changed it to a grid but am getting the same results as the canvas; the rectangles don't want to stretch horizontally or vertically. If I do set a horz/vert alignment the histogram disappears altogether. Can anyone help with this problem?
I ended up making a class that was a derivative of the canvas class i cave it some rendering overrides and a paint method that took into account the actual width and height of the window.

WPF Resizable Canvas

I need to implement a Canvas which scales its contents according to its size. I know there is Viewbox, which scales everything inside of it. However I cannot use that, because some elements have a fixed size and cannot be scaled.
Also how can I bind the size of the Canvas to the parent element (for example a resizable window). There is sizeToContent for windows, I want the size fitting exactly the other way round. Also the canvas uses some drawing based on the size of the hosting element, how is redraw triggered and how can I ensure that it only draws if it gets a valid (or min) size?
If you don't specify any width or height to the canvas it automatically uses all the available space. This is because the default VerticalAlignment and HorizontalAlignment are set to Stretch.
What do you mean by canvas that scales it's contents according to it's size without scaling all the contents as some have fixed size?
Update after comments
If your drawing algorithm already scales the content to the canvas' height and width then all you need to do is to resize the canvas to fit the area I believe? In that case just remove the hardcoded height/width values and the canvas will resize to fit the container.
You might need to use ActualHeight/ActualWidth instead of Height/Width in the drawing algorithm after this though. ActualHeight/ActualWidth return the values that the layout container will give your canvas so these represents the values the canvas is drawn with.
I think you can find the answers to all your questions in my London Underground demo.
I'm doing this from memory, but if I recall correctly a Window uses either a Panel or a Canvas as part of it's ControlTemplate (in which lies the ContentPresenter), which means that a Canvas placed directly in a Window will have issues resizing automatically like it might elsewhere. There are a few basic ways to address this.
1 Write a new ControlTemplate for your Window to use. :(2 Place your content directly in the Window rather than in a Canvas inside the Window. :/
3 Do a by-name binding. :)
<MyWindow x:Name="topWindow">
<Canvas x:Name="topCanvas" Width="{Binding ElementName=topWindow, Path=ActualWidth}" Height="{Binding ElementName=topWindow, Path=ActualHeight}">
...Content...
</Canvas>
</MyWindow>
(As it happens, I often bind grids inside Canvases in this fashion, so I can easily animate items moving from one grid position to another.)

Resources