网格创建我不想要的额外间距 [英] Grid creating extra spacing that I don't want

查看:145
本文介绍了网格创建我不想要的额外间距的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用嵌套的Grids在WPF应用程序中创建了一个有点大的输入表单。

 < Window x:Class =Gridtest.MainWindow
xmlns =http://schemas.microsoft.com/winfx/2006/xaml/presentation
xmlns:x =http ://schemas.microsoft.com/winfx/2006/xaml
Title =MainWindow>

<网格>
< Grid.ColumnDefinitions>
< ColumnDefinition Width =16 */>
< ColumnDefinition Width =10 */>
< /Grid.ColumnDefinitions>
< Grid.RowDefinitions>
< RowDefinition Height =Auto/>
< RowDefinition Height =Auto/>
< RowDefinition Height =Auto/>
< RowDefinition Height =Auto/>
< /Grid.RowDefinitions>

< Grid Grid.Column =0Grid.Row =0Grid.RowSpan =2>
< Grid.ColumnDefinitions>
< ColumnDefinition Width =Auto/>
< ColumnDefinition Width =136 */>
< ColumnDefinition Width =271 */>
< /Grid.ColumnDefinitions>
< Grid.RowDefinitions>
< RowDefinition Height =Auto/>
< RowDefinition Height =Auto/>
< RowDefinition Height =Auto/>
< RowDefinition Height =Auto/>
< RowDefinition Height =Auto/>
< RowDefinition Height =Auto/>
< RowDefinition Height =Auto/>
< RowDefinition Height =Auto/>
< /Grid.RowDefinitions>

< Label Grid.Row =0Grid.Column =0Content =Battery Name/>
< Label Grid.Row =1Grid.Column =0Content =FDC Callsign/>
< Label Grid.Row =2Grid.Column =0Content =Battery Type/>
< Label Grid.Row =3Grid.Column =0Content =GRID/>
< Label Grid.Row =4Grid.Column =0Content =ALT/>
< Label Grid.Row =5Grid.Column =0Content =Fire of Dir。/>
< Label Grid.Row =6Grid.Column =0Content =Target Prefix/>
< Label Grid.Row =7Grid.Column =0Content =Target#Start/>

< Grid Grid.Column =1Grid.ColumnSpan =2>
< Grid.ColumnDefinitions>
< ColumnDefinition />
< ColumnDefinition Width =Auto/>
< /Grid.ColumnDefinitions>

< ComboBox x:Name =EBattNameIsEditable =TrueItemsSource ={Binding BatteryList}SelectedItem ={Binding SelectedBattery,Mode = TwoWay}DisplayMemberPath =Name/> gt ;
< Button x:Name =EBattSaveGrid.Column =1Content =Add/>
< / Grid>
< TextBox x:Name =EBattCallsignGrid.Row =1Grid.Column =1DataContext ={Binding SelectedBattery}Text ={Binding Callsign}Grid.ColumnSpan =2 />
< ComboBox x:Name =EBattTypeGrid.Row =2Grid.Column =1Grid.ColumnSpan =2DataContext ={Binding SelectedBattery}SelectedItem ={Binding BWeapon} DisplayMemberPath =Designation/>
< / Grid>

< Grid Grid.Column =0Grid.Row =2>
< Grid.RowDefinitions>
< RowDefinition Height =Auto/>
< RowDefinition Height =Auto/>
< /Grid.RowDefinitions>
< Grid.ColumnDefinitions>
< ColumnDefinition />
< ColumnDefinition />
< ColumnDefinition />
< /Grid.ColumnDefinitions>
< Label Grid.ColumnSpan =3Content =NEW MISSION/>

< Button x:Name =BMissionGridGrid.Row =1Content =GRID/>
< Button x:Name =BMissionPolarGrid.Column =1Grid.Row =1Content =POLAR/>



我从我的项目中提取它并删除指向我的项目命名空间的所有事件处理程序和绑定,以便您可以将其粘贴到新的WPF应用程序项目中并亲自查看。



以下是结果窗口:

设计视图:(以红色标记的额外空间)


运行时视图:

ASCII视图应该是这样的:

 
---------------
| 1 | |
-------- | 3 |
| 2 | |
---------------
| 4 |
---------------

它创造了大量的垂直我不想要的间距。
这是从哪里来的?我如何修复它?
正如我在上面的代码中所标记的,向其中一个网格添加 Margin =0,0,0,-200有所帮助,但这似乎很有帮助丑陋。



我可能会从头开始重建网格,使其嵌套更少,但仍然认为这不应该发生。



编辑:我用最小的嵌套重建了网格,所以它只是一个包含所有元素的大网格:

 < Grid> 
< Grid.ColumnDefinitions>
< ColumnDefinition Width =Auto/><! - Left Labels - >
< ColumnDefinition Width =10 */><! - Left Edit controls - >
< ColumnDefinition Width =Auto/><! - 右标签 - >
< ColumnDefinition Width =7 */><! - 右编辑控件 - >
< /Grid.ColumnDefinitions>
< Grid.RowDefinitions>
< RowDefinition Height =Auto/> <! - 它自己的行中的所有内容 - >
< RowDefinition Height =Auto/>
< RowDefinition Height =Auto/>
< RowDefinition Height =Auto/>
< RowDefinition Height =Auto/>
< RowDefinition Height =Auto/>
< RowDefinition Height =Auto/>
< RowDefinition Height =Auto/>
< RowDefinition Height =Auto/>
< RowDefinition Height =Auto/>
< RowDefinition Height =Auto/>
< RowDefinition Height =*/> <! - 此行中的列表视图 - >
< /Grid.RowDefinitions>

<! - 这里的元素 - >

< / Grid>

而且没有任何明显问题。

解决方案

我正在测试你的代码,并注意到一些奇怪的行为。您的面板应呈现如下:

 
---------------
| 1 | |
-------- | 3 |
| 2 | |
---------------
| 4 |
---------------

但他们目前正在渲染,额外的空间被添加到2和3单元格的底部。

 
------------ ---
| 1 | |
-------- | 3 |
| 2 | |
| | |
---------------
| 4 |
---------------

由于某些原因,单元格# 3是通过在底部添加额外空间来扩展单元格高度。



奇怪的是,我发现这只发生在您的 RowSpan 被设置为奇数。如果您将其设置为2或4,则显示效果会很好。

 < Grid> 
< Grid x:Name =1Grid.Column =0Grid.Row =0... />
< Grid x:Name =2Grid.Column =0Grid.Row =1... />
< Grid x:Name =3Grid.Column =1Grid.Row =0Grid.RowSpan =2... />
< Grid x:Name =4Grid.Column =0Grid.Row =3Grod.ColumnSpan =2... />
< / Grid>

<网格>
< Grid x:Name =1Grid.Column =0Grid.Row =0Grid.RowSpan =3... />
< Grid x:Name =2Grid.Column =0Grid.Row =3... />
< Grid x:Name =3Grid.Column =1Grid.Row =0Grid.RowSpan =4... />
< Grid x:Name =4Grid.Column =0Grid.Row =4Grod.ColumnSpan =2... />
< / Grid>

删除单元格#3中的大部分元素可以正确绘制单元格的高度, #3中元素的数量会缩小高度,但不会消除它,所以也许它与计算边距或填充有关?



所以我的建议是像第一个例子那样创建RowSpan = 2,或者更改面板布局,使其如下所示:

 < StackPanel> 
< DockPanel>
< Grid x:Name =3DockPanel.Dock =Right... />
< Grid x:Name =2DockPanel.Dock =Top... />
< Grid x:Name =1... />
< / DockPanel>
< Grid x:Name =4... />
< / StackPanel>



A <$如果可能的话,c $ c> Grid 的目的是让它的子对象填充所有可用的空间。



你正在设置 Height =Auto,这意味着行默认只占用渲染其控件所需的空间量。然而,由于 Grid 的工作方式,它会尝试并拉伸至少一行以填充所有可用空间。

通常,这个拉伸过程是平等的,所有的行都被赋予相等的额外空间,正如您在Design Time窗口中看到的那样。但是因为你的第二列只有两个对象,一个是 RowSpan = 3 ,它看起来像在运行时它决定在组合的1-2-3行和行4.



为了避免这种情况,请确保至少指定一个 * 高度行占用所有剩余的空间,即使这是底部的空白行。

 < Grid.ColumnDefinitions> 
< ColumnDefinition Width =16 */>
< ColumnDefinition Width =10 */>
< /Grid.ColumnDefinitions>
< Grid.RowDefinitions>
< RowDefinition Height =Auto/>
< RowDefinition Height =Auto/>
< RowDefinition Height =Auto/>
< RowDefinition Height =Auto/>
< RowDefinition Height =*/> <! - 第五行占据所有可用空间 - >
< /Grid.RowDefinitions>

或切换到不同的面板没有这种行为,比如 DockPanel LastChildFill =False StackPanel




I created a somewhat large input form in a WPF application, using nested Grids. I'm using VS2010 and VS2012 Ultimate.

Here is the code:

<Window x:Class="Gridtest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow">

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="16*"/>
        <ColumnDefinition Width="10*"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>

    <Grid Grid.Column="0" Grid.Row="0" Grid.RowSpan="2">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="136*"/>
            <ColumnDefinition Width="271*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <Label Grid.Row="0" Grid.Column="0" Content="Battery Name"/>
        <Label Grid.Row="1" Grid.Column="0" Content="FDC Callsign"/>
        <Label Grid.Row="2" Grid.Column="0" Content="Battery Type"/>
        <Label Grid.Row="3" Grid.Column="0" Content="GRID"/>
        <Label Grid.Row="4" Grid.Column="0" Content="ALT"/>
        <Label Grid.Row="5" Grid.Column="0" Content="Dir. of Fire"/>
        <Label Grid.Row="6" Grid.Column="0" Content="Target Prefix"/>
        <Label Grid.Row="7" Grid.Column="0" Content="Target # Start"/>

        <Grid Grid.Column="1" Grid.ColumnSpan="2">
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>

            <ComboBox x:Name="EBattName"  IsEditable="True" ItemsSource="{Binding BatteryList}" SelectedItem="{Binding SelectedBattery, Mode=TwoWay}" DisplayMemberPath="Name"/>
            <Button x:Name="EBattSave" Grid.Column="1" Content="Add"/>
        </Grid>
        <TextBox x:Name="EBattCallsign" Grid.Row="1" Grid.Column="1" DataContext="{Binding SelectedBattery}" Text="{Binding Callsign}" Grid.ColumnSpan="2"/>
        <ComboBox x:Name="EBattType" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" DataContext="{Binding SelectedBattery}" SelectedItem="{Binding BWeapon}" DisplayMemberPath="Designation"/>
        <TextBox x:Name="EBattGrid" Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="2" DataContext="{Binding SelectedBattery}" Text="{Binding Coords.Grid}"/>
        <TextBox x:Name="EBattAlt" Grid.Row="4" Grid.Column="1" Grid.ColumnSpan="2" DataContext="{Binding SelectedBattery}" Text="{Binding Coords.Altitude}"/>
        <TextBox x:Name="EBattDir" Grid.Row="5" Grid.Column="1" Grid.ColumnSpan="2" DataContext="{Binding SelectedBattery}" Text="{Binding Dir}"/>
        <TextBox x:Name="EBattPre" Grid.Row="6" Grid.Column="1" Grid.ColumnSpan="2" DataContext="{Binding SelectedBattery}" Text="{Binding Prefix}"/>
        <TextBox x:Name="EBattStart" Grid.Row="7" Grid.Column="1" Grid.ColumnSpan="2" DataContext="{Binding SelectedBattery}" Text="{Binding Start}"/>
    </Grid>

    <Grid Grid.Column="0" Grid.Row="2">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Label Grid.ColumnSpan="3" Content="NEW MISSION"/>

        <Button x:Name="BMissionGrid" Grid.Row="1" Content="GRID"/>
        <Button x:Name="BMissionPolar" Grid.Column="1"  Grid.Row="1" Content="POLAR"/>
        <Button x:Name="BMissionShift" Grid.Column="2"  Grid.Row="1" Content="SHIFT"/>
    </Grid>

    <!-- Adding negative bottom margin to this grid helps... -->
    <Grid Grid.Column="1" Grid.Row="0" Grid.RowSpan="3" >
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <Label Grid.Row="0" Grid.ColumnSpan="2" Content="OBSERVER INFORMATION"/>

        <Label Grid.Row="1" Grid.Column="0" Content="Select"/>
        <Label Grid.Row="2" Grid.Column="0" Content="Name"/>
        <Label Grid.Row="3" Grid.Column="0" Content="Grid"/>
        <Label Grid.Row="4" Grid.Column="0" Content="Alt"/>


        <Grid  Grid.Row="1" Grid.Column="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <ComboBox Grid.Column="0" x:Name="EObsSelect" ItemsSource="{Binding SelectedBattery.Observers}" SelectedItem="{Binding SelectedObserver, Mode=TwoWay}" DisplayMemberPath="Name" />
            <Button Grid.Column="1" x:Name="BObserverAdd" Content="New"/>
        </Grid>

        <TextBox x:Name="EObsName" Grid.Row="2" Grid.Column="1" Text="{Binding SelectedObserver.Name}"          />
        <TextBox x:Name="EObsGrid" Grid.Row="3" Grid.Column="1" Text="{Binding SelectedObserver.Coord.Grid}"    />
        <TextBox x:Name="EObsAlt" Grid.Row="4" Grid.Column="1"  Text="{Binding SelectedObserver.Coord.Altitude}"/>

        <Label Grid.ColumnSpan="2" Grid.Row="5" Content="KNOWN POINTS"/>

        <Label Grid.Row="6" Grid.Column="0" Content="Select"/>
        <Label Grid.Row="7" Grid.Column="0" Content="Name"/>
        <Label Grid.Row="8" Grid.Column="0" Content="Grid"/>
        <Label Grid.Row="9" Grid.Column="0" Content="Alt"/>

        <Grid  Grid.Row="6" Grid.Column="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <ComboBox x:Name="EKPSelect" Grid.Column="0" ItemsSource="{Binding SelectedBattery.Knownpoints}" SelectedItem="{Binding SelectedPoint, Mode=TwoWay}" DisplayMemberPath="Name"/>
            <Button Grid.Column="1" x:Name="BKnownpointAdd" Content="New"/>
        </Grid>

        <TextBox x:Name="EKPName" Grid.Row="7" Grid.Column="1"  Text="{Binding SelectedItem.Name, ElementName=EKPSelect}"          />
        <TextBox x:Name="EKPGrid" Grid.Row="8" Grid.Column="1"  Text="{Binding SelectedItem.Coord.Grid, ElementName=EKPSelect}"    />
        <TextBox x:Name="EKPAlt" Grid.Row="9" Grid.Column="1"   Text="{Binding SelectedItem.Coord.Altitude, ElementName=EKPSelect}"/>
    </Grid>


    <Grid Grid.Column="0" Grid.Row="3" Grid.ColumnSpan="2">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>

        <Label Content="MISSION LIST"/>

        <ListView Grid.Row="1" SelectionMode="Single"
            DataContext="{Binding SelectedBattery}"
            ItemsSource="{Binding Missions}"
                  >
            <ListView.View>
                <GridView>
                    <GridViewColumn DisplayMemberBinding="{Binding TargetNumber}" Header="Target No"/>
                    <GridViewColumn DisplayMemberBinding="{Binding TargetDescription}" Header="Description"/>
                    <GridViewColumn DisplayMemberBinding="{Binding Coords.Grid}" Header="Location"/>
                    <GridViewColumn DisplayMemberBinding="{Binding Coords.Altitude}" Header="Altitude"/>
                    <GridViewColumn DisplayMemberBinding="{Binding Attitude}" Header="Attitude"/>
                    <GridViewColumn DisplayMemberBinding="{Binding Length}" Header="Length"/>
                    <GridViewColumn DisplayMemberBinding="{Binding Radius}" Header="Radius"/>
                    <GridViewColumn DisplayMemberBinding="{Binding Notes}" Header="Remarks"/>
                </GridView>
            </ListView.View>
        </ListView>

    </Grid>

</Grid>

I extracted it from my project and removed all the event handlers and bindings pointing into my project namespace so you can take this and paste it into a new WPF Application project and see for yourself.

Here is the resulting window:

Design view: (extra spacing marked in red there)
Runtime view:

ASCII View of what it should look like:

---------------
|   1   |     |
--------|  3  |
|   2   |     |
---------------
|      4      |
---------------

It creates humongous amounts of vertical spacing that I don't want. Where is this coming from? How can I fix it? As I marked in the code above, adding Margin="0,0,0,-200" to one of the grids helps somewhat, but that seems very ugly.

I'm probably going to rebuild the grid from the ground up to make it less nested, but still, it seems to me like this shouldn't be happening.

EDIT: I rebuilt the grid with minimal nesting, so it's just one big grid with all the elements put into it:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/><!-- Left Labels -->
        <ColumnDefinition Width="10*"/><!-- Left Edit controls --> 
        <ColumnDefinition Width="Auto"/><!-- Right labels -->
        <ColumnDefinition Width="7*"/><!-- Right Edit controls -->
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" /> <!-- Everything in its own row -->
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*"    /> <!-- Listview in this row -->
    </Grid.RowDefinitions>

    <!-- Elements here -->

</Grid>

And that works without any apparent issues.

解决方案

I was testing with your code and noticed some strange behavior. Your panels should render like this:

---------------
|   1   |     |
--------|  3  |
|   2   |     |
---------------
|      4      |
---------------

But they're currently rendering like this, with extra space being added to the bottom of both the 2 and 3 cells.

---------------
|   1   |     |
--------|  3  |
|   2   |     |
|       |     |
---------------
|      4      |
---------------

For some reason, elements added in cell #3 are extending the cell height by adding extra space at the bottom.

Strangely enough, I found this only occurs when your RowSpan for cell #3 is set to an odd number. If you set that to 2 or 4, it appears to render just fine.

<Grid>
    <Grid x:Name="1" Grid.Column="0" Grid.Row="0" ... />
    <Grid x:Name="2" Grid.Column="0" Grid.Row="1" ... />
    <Grid x:Name="3" Grid.Column="1" Grid.Row="0" Grid.RowSpan="2" ... />
    <Grid x:Name="4" Grid.Column="0" Grid.Row="3" Grod.ColumnSpan="2" ... />
</Grid>

<Grid>
    <Grid x:Name="1" Grid.Column="0" Grid.Row="0" Grid.RowSpan="3" ... />
    <Grid x:Name="2" Grid.Column="0" Grid.Row="3" ... />
    <Grid x:Name="3" Grid.Column="1" Grid.Row="0" Grid.RowSpan="4" ... />
    <Grid x:Name="4" Grid.Column="0" Grid.Row="4" Grod.ColumnSpan="2" ... />
</Grid>

Removing most of the elements in cell #3 correctly draws the cells to the correct height, and reducing the number of elements in #3 will shrink the height, but not eliminate it, so perhaps it has something to do with calculating the margin or padding?

So my suggestion would be to make the RowSpan=2 like the first example, or change your panel layout so it's like this:

<StackPanel>
    <DockPanel>
        <Grid x:Name="3" DockPanel.Dock="Right" ... />
        <Grid x:Name="2" DockPanel.Dock="Top" ... />
        <Grid x:Name="1" ... />
    </DockPanel>
    <Grid x:Name="4" ... />
</StackPanel>

A Grid is designed to make its children fill all available space if possible.

You are setting Height="Auto" on all your rows, which means rows will by default take up only the amount of space they need to render their controls. However because of the way a Grid works, it's going to try and stretch at least one of those rows to fill all available space.

Typically this stretch is done equally, with all the rows getting assigned an equal amount of the extra space, as you can see in your Design Time window. But since your 2nd column has only two objects, one with RowSpan=3, it looks like at runtime it decided to split the extra space equally between the combined 1-2-3 row, and row 4.

To avoid this behavior, make sure to specify at least one * height row to take up all remaining space, even if that is a blank row at the bottom.

<Grid.ColumnDefinitions>
    <ColumnDefinition Width="16*"/>
    <ColumnDefinition Width="10*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
    <RowDefinition Height="Auto"/>
    <RowDefinition Height="Auto"/>
    <RowDefinition Height="Auto"/>
    <RowDefinition Height="Auto"/>
    <RowDefinition Height="*"/> <!-- 5th row to take up all available space -->
</Grid.RowDefinitions>

Or switch to a different Panel that doesn't have this behavior, such as a DockPanel with LastChildFill="False", or StackPanel

这篇关于网格创建我不想要的额外间距的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆