When I clicked on the maximize button the window is maximized but the controls are not resized proportionally. What is the best way to make the controls resize accordingly? I am using MVVM.
Here is my code.
<Window x:Class="DataTransfer.View.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Icon="/DataTransfer;component/View/Images/ms_msnexplore.gif" ResizeMode="CanResizeWithGrip" Title="Window1" Height="500" Width="600"> <!--Style="{DynamicResource OfficeStyle}"--> <Window.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <!--<ResourceDictionary Source="/DataTransfer;component/View/WindowBase.xaml" />--> <!--<ResourceDictionary Source="/DataTransfer;component/Themes/WPFThemes/CalendarResource.xaml" />--> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Window.Resources> <Grid> <Grid.RowDefinitions> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width ="*" /> </Grid.ColumnDefinitions> <Button Content="Button" HorizontalAlignment="Left" Margin="52,28,0,0" VerticalAlignment="Top" Width="75" Height="22" /> <DatePicker Name="dp" HorizontalAlignment="Left" Margin="175,25,0,0" VerticalAlignment="Top" Width="123" Text="aaa" GotFocus="DateGotFocused" LostFocus="OnLeaveArchiveDate"/> <Calendar HorizontalAlignment="Left" Margin="47,162,0,0" VerticalAlignment="Top"/> <TextBox Name="t1" HorizontalAlignment="Left" Height="23" Margin="337,23,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120" LostFocus="LeaveField" /> <RadioButton Content="RadioButton" HorizontalAlignment="Left" Margin="88,92,0,0" VerticalAlignment="Top"/> <CheckBox Content="CheckBox" HorizontalAlignment="Left" Margin="252,96,0,0" VerticalAlignment="Top"/> <ComboBox Name="combo" IsEditable="False" Text="aaa" IsReadOnly="True" HorizontalAlignment="Left" Margin="337,89,0,0" VerticalAlignment="Top" Width="120" Focusable="True" GotFocus="ComboBoxGotFocused" > <ComboBoxItem>January</ComboBoxItem> <ComboBoxItem>February</ComboBoxItem> </ComboBox> <TextBlock HorizontalAlignment="Left" Height="40" Margin="260,184,0,0" TextWrapping="Wrap" Text="Text_Block" VerticalAlignment="Top" Width="257"/> </Grid> </Window>
In WPF there are certain 'container' controls that automatically resize their contents and there are some that don't.
Here are some that do not resize their contents (I'm guessing that you are using one or more of these):
StackPanel WrapPanel Canvas TabControl
Here are some that do resize their contents:
Grid UniformGrid DockPanel
Therefore, it is almost always preferable to use a Grid
instead of a StackPanel
unless you do not want automatic resizing to occur. Please note that it is still possible for a Grid
to not size its inner controls... it all depends on your Grid.RowDefinition
and Grid.ColumnDefinition
settings:
<Grid> <Grid.RowDefinitions> <RowDefinition Height="100" /> <!--<<< Exact Height... won't resize --> <RowDefinition Height="Auto" /> <!--<<< Will resize to the size of contents --> <RowDefinition Height="*" /> <!--<<< Will resize taking all remaining space --> </Grid.RowDefinitions> </Grid>
You can find out more about the Grid
control from the Grid
Class page on MSDN. You can also find out more about these container controls from the WPF Container Controls Overview page on MSDN.
Further resizing can be achieved using the FrameworkElement.HorizontalAlignment
and FrameworkElement.VerticalAlignment
properties. The default value of these properties is Stretch
which will stretch elements to fit the size of their containing controls. However, when they are set to any other value, the elements will not stretch.
UPDATE >>>
In response to the questions in your comment:
Use the Grid.RowDefinition
and Grid.ColumnDefinition
settings to organise a basic structure first... it is common to add Grid
controls into the cells of outer Grid
controls if need be. You can also use the Grid.ColumnSpan
and Grid.RowSpan
properties to enable controls to span multiple columns and/or rows of a Grid
.
It is most common to have at least one row/column with a Height
/Width
of "*"
which will fill all remaining space, but you can have two or more with this setting, in which case the remaining space will be split between the two (or more) rows/columns. 'Auto' is a good setting to use for the rows/columns that are not set to '"*"', but it really depends on how you want the layout to be.
There is no Auto
setting that you can use on the controls in the cells, but this is just as well, because we want the Grid
to size the controls for us... therefore, we don't want to set the Height
or Width
of these controls at all.
The point that I made about the FrameworkElement.HorizontalAlignment
and FrameworkElement.VerticalAlignment
properties was just to let you know of their existence... as their default value is already Stretch
, you don't generally need to set them explicitly.
The Margin
property is generally just used to space your controls out evenly... if you drag and drop controls from the Visual Studio Toolbox, VS will set the Margin
property to place your control exactly where you dropped it but generally, this is not what we want as it will mess with the auto sizing of controls. If you do this, then just delete or edit the Margin
property to suit your needs.
Well, it's fairly simple to do.
On the window resize event handler, calculate how much the window has grown/shrunk, and use that fraction to adjust 1) Height, 2) Width, 3) Canvas.Top, 4) Canvas.Left properties of all the child controls inside the canvas.
Here's the code:
private void window1_SizeChanged(object sender, SizeChangedEventArgs e) { myCanvas.Width = e.NewSize.Width; myCanvas.Height = e.NewSize.Height; double xChange = 1, yChange = 1; if (e.PreviousSize.Width != 0) xChange = (e.NewSize.Width/e.PreviousSize.Width); if (e.PreviousSize.Height != 0) yChange = (e.NewSize.Height / e.PreviousSize.Height); foreach (FrameworkElement fe in myCanvas.Children ) { /*because I didn't want to resize the grid I'm having inside the canvas in this particular instance. (doing that from xaml) */ if (fe is Grid == false) { fe.Height = fe.ActualHeight * yChange; fe.Width = fe.ActualWidth * xChange; Canvas.SetTop(fe, Canvas.GetTop(fe) * yChange); Canvas.SetLeft(fe, Canvas.GetLeft(fe) * xChange); } } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With