Container for relatively positioned children - c#

Using WPF, I need something like Canvas, but with the option that elements are sized in relation to the canvas. I'm displaying an Image and multiple Rectangle elements and would like to have the image as well as the rectangles sized when the container is resized. Using a Canvas, the elements always retain the original size.

The answer is to use a ViewBox around your Canvas. Try this:
<ViewBox>
<Canvas>
<!-- Your elements -->
</Canvas>
</ViewBox>
You should set the Stretch and StretchDirection properties according to your needs. The ViewBox will scale all UI elements inside equally. Please see the first linked page on MSDN for further help with this class.

You are looking for ViewBox. And yes, it's a short, but an answer =P.

Related

WPF Scrolling AutoSizing Panel

I have a WPF application in which the main window holds a DockPanel with two children. The top child is another DockPanel which holds the menu and is of a fixed size. The lower child is the main work area, which should fill the remaining space and be resizable along with the window. (Hence the DockPanel parent.) Draggable objects get placed in this work area and might appear anywhere inside it.
I'm trying to figure out how to make scroll bars appear if an object is dragged outside the visible area.
The approximate XAML structure currently goes
<Window>
<DockPanel>
<DockPanel with fixed-size content ... >
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Grid ClipToBounds="True" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"/>
</ScrollViewer>
</DockPanel>
</Window>
So far I've tried a Grid and a Canvas. Both have built-in scroll bars, but they won't appear unless dimensions are specified--but if I apply dimensions, then the panel won't automatically resize to fill the work area.
Then I tried surrounding the panel with a ScrollViewer. The unconstrained panel now successfully auto-resizes to fill the space, but the ScrollViewer has the same problem as the panel--it will only display scroll bars if it's constrained to hard dimensions.
I'm thinking that this would work if I could dynamically constrain the ScrollViewer. So far, I haven't found any reliable way to dynamically apply size values to the ScrollViewer.
Is there a way to create a Binding between the ScrollViewer dimensions and the ActualHeight and ActualWidth of the Grid? Or, is there a way I can define the ActualHeight/ActualWidth of the grid as a DynamicResource that can be applied to the ScrollViewer? Or is there some other panel or method or resource that can be used so that all three criteria (panel fills available space, panel auto-resizes with window, anything dragged outside visible area triggers scroll bars) are met?
Thanks in advance for any help.
The problem was that I did not have a DockPanel.Dock setting on the bottom child of the containing DockPanel. Relying on the DockPanel's LastChildFill wasn't enough to do the job. Once I set DockPanel.Dock = Bottom on the bottom child, the scroll bars started working.

How do you get XAML elements to scale to fit their containers?

I understand that there are a variety of ways to size child elements according to parent elements. If you're using a grid for example, you can use row and column definitions and you get lots of freedom regarding automatic sizes or fixed sizes or "star" sizes. However, if the child elements themselves have a fixed width and height then it won't matter if the parent tells the child to fill all available space. The child element will remain the same size.
I have a window that was designed to always display its contents at the same pixel dimensions no matter what size the window is resized to. Rather than go and change every single child element in every XAML page so that it doesn't have a fixed size, I'd like to get the main Grid to just scale to fit the window. So far the only way to get elements with fixed dimensions to display at different sizes is to use Transform scaling, either with a RenderTransform or a LayoutTransform. But if I go that route, I'll have to code the scaling in C# to respond to resizing events rather than have it happen automatically. Is there some native builtin way to do this in XAML? This feels like the kind of thing I should be able to do with some special property, or perhaps a ContentControl or ContentPresenter.
I've seen Resize WPF Window and contents depening on screen resolution but it's asking about conventional resizing and not scaling fixed elements. I've also seen How to make all controls resize accordingly proportionally when window is maximized? and that has the same problem though the second answer at least talks about handling resizing events.
Here's a simplified example of a fixed-dimension child element not resizing as desired:
<Window x:Class="WpfTest.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="Window1" Height="200" Width="300" Background="LightBlue">
<Grid>
<Frame Background="Blue" Width="200" Height="100">
</Frame>
</Grid>
</Window>
Actual results:
Desired results:
As you can see, what I'm looking for is a sort of letterboxing effect, meaning I want the aspect ratio to be maintained. However, I haven't found a way to get automatic scaling even without worrying about the aspect ratio, so I thought I'd consider the letterboxing as a sort of second phase that I'd worry about later.
The control you are looking for is a Viewbox. It grows to fill its container (you can set the stretch style for the letterboxing) and scales all its contents accordingly. Just make it the root element of your application (or whatever you want stretched):
<Viewbox>
<Grid> //Or whatever
<OtherStuff>
</Grid>
</Viewbox>
Note that because the viewbox is scaling its contents traditional Grid behavior and similar will stop working since the size of the content never actually changes.
Another option is to use a MultiValueConverter to set the height and width.
You could give the Converter the ActualWidth and ActualHeight of the root container als parameters and let it calculate the needed aspect ratio.
A tutorial which describes the MultiValueConverter:
http://www.wpftricks.com/2017/05/wpf-multivalueconverter.html

I'm having trouble positioning elements in a Grid when the window is resized

I have a 50x50 draggable grid inside another grid that I am able to move around with the cursor. (I forgot that I am using the DraggableExtender class
The problem is that I want the moveable grid to be relatively positioned inside it's container grid no matter how the container grid is resized. My solution right now is to dynamically change the HorizontalAlignment and VerticalAlignment of the moveable grid whenever it is moved, but this is hacky and doesn't work well.
Relative positioning in a grid is one of the easiest things to do in XAML, but not when you have draggable elements ;(
Any ideas?
EDIT for code and images:
My XAML:
<Grid Margin="10" ClipToBounds="True" Background="#FFB4B4B4">
<Grid Name="testGrid" MouseLeftButtonDown="testGrid_MouseLeftButtonDown" MouseLeftButtonUp="testGrid_MouseLeftButtonUp" RenderTransformOrigin="0.5,0.5" Height="100" Margin="50,0,0,0" Width="100" Background="#FFE6E6E6" local:DraggableExtenderGrid.CanDrag="true" HorizontalAlignment="Center"/>
</Grid>
and I use a DraggableExtender class (shown here) which I have edited to apply to a Grid instead of a Canvas (I was hoping for better results from a grid.. but both containers produce the same result, even with the original class on a canvas).
This is a picture of my 2 grids. I can move the smaller grid around inside it's parent grid, but I would like for it to maintain relative positioning once the window is resized. This is what it currently looks like when I resize the window. In this particular example, the grid would ideally remain slightly off-center horizontally and vertically in both pictures.
May be you should try placing the Grid inside a Canvas instead..
Take a look here

What is the Alternative of PictureBox in Silverlight?

i have a PictureBox in my Windows Form application and i am in the process of converting my application to Silverlight and i would like to know what is the alternative of PictureBox in Silverlight, Thank you!
Depending on the functionality of the PictureBox you are using, you could just use the Image control in Silverlight.
Image control is your only choice for this case, but you should be careful that this control just support .jpg and .png image extentions and for other formats you must create or use converters
What you might want to try is the Viewbox control. Then, inside of the Viewbox you can place an image. The great thing about the Viewbox is that you can always scale everything inside consistently, even as the VB resizes. Or, you can use the Image as #Chris pointed out and provided size limits and a scale setting.
Sample XAML:
<Viewbox x:Name="vb">
<Image x:Name="myImage" Source="pathToImage"/>
</Viewbox>
You could then place the Viewbox inside a Stackpanel or Grid to achieve proper layout. Hope this helps!

Adorners overlap controls that are above the adorned element

Hey, I'm having an issue with adorners. I created resize adorners which have four Thumb controls, one for each of the corners of the control being decorated. The control is being drawn on a Canvas, and the user may select it and resize it.
The canvas is hosted on a ZoomBoxPanel control, which basically applies a ScaleTransform and TranslateTransform to the whole thing to provide zoom and pan support.
Problem is that when an item is outside the bounds of the zoom panel, and the item is cropped as you'd expect (like when you set ClipToBounds = true), you can still see the adorners! Could anyone please tell me a way to prevent this?
Evidence. The black square is the one selected, two resize thumbs are visible (right), the others should not be visible (left)
Thanks!!
Fixed it, solution was to put an AdornerDecorator object immediately above the Canvas :)
<AdornerDecorator>
<Canvas>
</AdornerDecorator>

Categories

Resources