当窗口最大化时,如何使所有控件相应地调整大小?

时间:2022-11-30 19:00:26

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.

当我点击最大化按钮时,窗口是最大化的,但是控件不是按比例大小调整的。使控件调整大小的最佳方法是什么?我使用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>

2 个解决方案

#1


74  

In WPF there are certain 'container' controls that automatically resize their contents and there are some that don't.

在WPF中,有一些“容器”控件可以自动调整其内容的大小,还有一些则没有。

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:

因此,使用网格而不是堆栈面板几乎总是更可取的,除非您不希望自动调整大小。请注意,网格仍然可以不调整内部控件的大小……这一切都取决于你的网格。RowDefinition和网格。ColumnDefinition设置:

<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.

您可以从MSDN上的Grid类页面找到更多关于网格控件的信息。您还可以从MSDN上的WPF容器控件概述页面中找到关于这些容器控件的更多信息。

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.

进一步调整大小可以使用FrameworkElement来实现。HorizontalAlignment FrameworkElement。VerticalAlignment属性。这些属性的默认值是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.

使用网格。RowDefinition和网格。列定义设置,首先组织一个基本结构……如果需要,通常将网格控件添加到外部网格控件的单元格中。您还可以使用网格。ColumnSpan和网格。RowSpan属性使控件能够跨多个列和/或网格的行。

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.

最常见的情况是,至少有一行/列的高度/宽度为“*”,这将填充所有剩余的空间,但是使用这种设置可以有两个或更多的行/列,在这种情况下,剩余的空间将在两个(或更多)行/列之间分割。“Auto”是一个很好的设置,可以用于没有设置为“*”的行/列,但它实际上取决于您希望布局的方式。

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.

关于FrameworkElement的问题。HorizontalAlignment FrameworkElement。垂直对齐属性只是让你知道它们的存在……由于它们的默认值已经扩展,所以通常不需要显式地设置它们。

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.

Margin属性通常用于均匀地分隔控件……如果您从Visual Studio工具箱中拖放控件,VS将设置Margin属性,使您的控件精确地放置在您丢弃的位置,但通常这不是我们想要的,因为它会扰乱控件的自动大小。如果您这样做,那么只需删除或编辑保证金属性以满足您的需要。

#2


3  

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.

在窗口调整事件处理程序上,计算窗口的增长/收缩量,并使用这个部分调整1)高度、2)宽度、3)画布。,4)画布。在画布内所有子控件的左属性。

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);

                }
            }
        }

#1


74  

In WPF there are certain 'container' controls that automatically resize their contents and there are some that don't.

在WPF中,有一些“容器”控件可以自动调整其内容的大小,还有一些则没有。

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:

因此,使用网格而不是堆栈面板几乎总是更可取的,除非您不希望自动调整大小。请注意,网格仍然可以不调整内部控件的大小……这一切都取决于你的网格。RowDefinition和网格。ColumnDefinition设置:

<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.

您可以从MSDN上的Grid类页面找到更多关于网格控件的信息。您还可以从MSDN上的WPF容器控件概述页面中找到关于这些容器控件的更多信息。

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.

进一步调整大小可以使用FrameworkElement来实现。HorizontalAlignment FrameworkElement。VerticalAlignment属性。这些属性的默认值是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.

使用网格。RowDefinition和网格。列定义设置,首先组织一个基本结构……如果需要,通常将网格控件添加到外部网格控件的单元格中。您还可以使用网格。ColumnSpan和网格。RowSpan属性使控件能够跨多个列和/或网格的行。

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.

最常见的情况是,至少有一行/列的高度/宽度为“*”,这将填充所有剩余的空间,但是使用这种设置可以有两个或更多的行/列,在这种情况下,剩余的空间将在两个(或更多)行/列之间分割。“Auto”是一个很好的设置,可以用于没有设置为“*”的行/列,但它实际上取决于您希望布局的方式。

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.

关于FrameworkElement的问题。HorizontalAlignment FrameworkElement。垂直对齐属性只是让你知道它们的存在……由于它们的默认值已经扩展,所以通常不需要显式地设置它们。

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.

Margin属性通常用于均匀地分隔控件……如果您从Visual Studio工具箱中拖放控件,VS将设置Margin属性,使您的控件精确地放置在您丢弃的位置,但通常这不是我们想要的,因为它会扰乱控件的自动大小。如果您这样做,那么只需删除或编辑保证金属性以满足您的需要。

#2


3  

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.

在窗口调整事件处理程序上,计算窗口的增长/收缩量,并使用这个部分调整1)高度、2)宽度、3)画布。,4)画布。在画布内所有子控件的左属性。

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);

                }
            }
        }