Filling WPF panel with images without scrolling or cropping - wpf

I'm displaying a variable number of images in a WPF window.
The images have varying widths and heights, but I'm setting the MaxWidth and MaxHeight for each.
I'm currently using a Wrap Panel, but I'm having trouble achieving what I want.
I don't want scrollbars and I want to load only as many images as will fit in the panel without getting cropped.
I've tried to do the math myself, but the images' ActualHeight and ActualWidth are both showing as 0 after I load them.
Any ideas?

Related

image gallery with scrollviewer - wrap panel does not respect boundaries of scroll viewer

I'm trying to create a gallery-style layout with a ScrollViewer and a WrapPanel in WPF, but the WrapPanel is extending beyond the boundaries of the ScrollViewer. I've tried setting the HorizontalAlignment and VerticalAlignment properties of the WrapPanel to "Left" and "Top" respectively, but it still doesn't stay within the boundaries of the ScrollViewer.
I've also tried setting the height of the WrapPanel to specific values and set the MaxHeight properties of the WrapPanel to limit the size, but it still doesn't stay within the boundaries of the ScrollViewer, and is no longer scrollable. I've also tried wrapping the WrapPanel inside a Grid and set the height of the Grid to the size I want and set the ClipToBounds property of the Grid as "True", but it still doesn't work.
I'm not sure what else I can do to keep the WrapPanel within the boundaries of the ScrollViewer. Can anyone help me figure out how to contain the WrapPanel within the ScrollViewer?
This is my xaml code:
<ScrollViewer Grid.Row="0">
<WrapPanel x:Name="Preview_WrapPanel"></WrapPanel>
</ScrollViewer>
and this is my result in my app, in the beginning, the distance from top is correct but the bottom not. I scrolled a little up to show that the height is not respected in the top region as well:
the width is respected, but i think only because this is the application width.
The thick red border is the area, which the scrollviewer occupies. The wrappanel should be contained inside, kind of like a window, where you can only see whats behind the window and not the trees behind the wall.
the wrappanel gets filled with WebView2 Media, each image around 200x200px:
WebView2 media = new WebView2();
media.Source = new Uri(nftFile.FullName);
media.Width = 200;
media.Height = 200;
this.Preview_WrapPanel.Children.Add(media);
I use Webview2 because the content could pretty much be anything, image, video, pdf, whatever. Also it supports webp
For now though, im only adding images.
There was a known bug with webview2 and it seems it has not been fixed.
Basically, renders on top so cannot be clipped.
https://github.com/MicrosoftEdge/WebView2Feedback/issues/2579
https://github.com/MicrosoftEdge/WebView2Feedback/issues/286
You need a different plan.
Maybe ensure it doesn't matter when they don't clip.
Maybe use images.
Or hope it gets fixed soon.
Andy was correct, this is a known issue. Microsoft knows about it since .net framework Times (>10 years) but refuses to fix the issue so far.
I solved the issue by Installing the Nuget Package CefSharp which uses the chromium engine as well.
What a pitty.

Crop WPF control

I have to crop some control to show only a half of it but the rest should be transparent and clickable so it is not enough to cover the control with something. The result should give a control with only half of the content (for example 50% of top) and the rest should be cropped (not hidden) so some other control below should be visible and not overlapped by cropped part. New control should also scale when window is scaled. How to do this in WPF?
I have finally did the trick using Border around the control and Clip property of this border was set to Multibinging that was generating Rectangle basing on ActualWidth and ActualHeight of my control
Maybe GridSplitter:
http://www.wpf-tutorial.com/panels/gridsplitter/
Can be used to split views horizontally/vertically, and can be responsive.

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.

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

How to make WPF WebBrowser grow horizontally and vertically?

In WPF, we are using a WebBrowser control to view HTML content. When we place the control on our window, it grows horizontally with the window as it grows/shrinks. However, we have not found a way to make the control grow vertically with the window. We are looking for some sample code that will allow the WebBrowser WPF control to grow both vertically and horizontally with the window.
With WPF and wanting to grow with the window, the magical starting point is to set the Margin to 0 and avoid setting width and height. (You can have margin equal to another number, but start with zero and see how it looks first!)
Another option is to use a dock panel with last child fill set to true, where the web browser control is the last element (as you read down the page - it doesn't have to be the last element in the rendered UI.

Resources