ViewBox automatically change postion of my control - wpf

I am writing an application using WPF in visual studio 2012.
I want to use Viewbox control to solve problem of resizing application. Now when I try to place other controls in Viewbox, I see that I can't change the position of controls. It seems that Viewbox change automatically the positions of controls!
Picture(1) is result
and picture(2) is what I want.
picture(1)
picture(2)
Please help me.

You need to specify how you want the ViewBox to align the child element it's stretching.
<Viewbox VerticalAlignment="Top">
Should place your elements at your desired location.
You can also specify how the ViewBox will Stretch it's content, and the HorizontalAlignment, if required.
Additionaly, you can specify StretchDirection="UpOnly", to ensure that your controls are never scaled below the initial size you specify.

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.

Sizing WPF windows automatically

When designing WPF dialog windows in the XAML designer (that are not manually resizeable by the user), the windows automatically resize to fit their content, and everything is fine. But when I run my app, the windows become huge and there's a lot of empty space.
I know this is a "feature" of WPF that can be "fixed" by setting the SizeToContent tag, but another issue arises when I do this: If the window contains a textbox, for instance, and the user enters data that overflows the visible area, the window will stretch to accommodate it. This happens with listboxes, treeviews, you name it.
All I want is for Visual Studio to figure out the ideal window size that it shows me at design time, then set the window to be that size at runtime, and don't change the size after that. It seems like this should be an easy thing to do.
Edit: Figured out part of the problem: I have controls set up in a grid, and the column's width is set to "Auto" which is why everything is resizing.
Use View Box
The ViewBox is a very useful control in WPF. If does nothing more than scale to fit the content to the available size. It does not resize the content, but it transforms it. This means that also all text sizes and line widths were scaled. Its about the same behavior as if you set the Stretch property on an Image or Path to Uniform.
Although it can be used to fit any type of control, it's often used for 2D graphics, or to fit a scalable part of a user interface into an screen area.
<Viewbox>
<Enter your code/>
</Viewbox>
Try setting the window's height and width to Auto. Also, remove the SizeToContent attribute. This should fix it.
I do not think that this is this is something which is commonly requested so it's probably not easy to do, one method i can think of would be starting with automatic SizeToContent and handling the Loaded event and setting:
Height = ActualHeight;
Width = ActualWidth;
SizeToContent = System.Windows.SizeToContent.Manual;

How to calculate a bounding box for an Expander?

I have an Expander control and i need to calculate its bounds without invisible elements and margins. It commonly can be done by VisualTreeHelper.GetDescendantsBounds. But it seems that the rect is calculated by VisualTreeHelper doesn't depend on the expander state. For example:
http://i.piccy.info/i5/58/39/273958/collapsed.jpg
(i can't post images. sorry)
The same result as for expanded state (light green rectangle on the image). Does anybody know how to solve this problem?
The Expander control will set its content's visibility to Collapsed, which means it won't be considered during layout and won't be included in GetDescendantBounds. However, the Expander can be forced to have a larger size by the layout engine, and the Expander's own size is included in GetDescendantBounds.
Try setting VerticalAlignment="Top" on the Expander. The default is Stretch, which will allow it to increase in size if the parent has more space available. Also make sure you aren't explicitly setting the Height property.
This is the sample application. The style is applied here to the TreeView control and its items. But the problem doesn't depend on the style.

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.

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