Grid creating extra spacing that I don't want

五迷三道 提交于 2019-12-24 01:38:07

问题


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.


回答1:


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



来源:https://stackoverflow.com/questions/16318773/grid-creating-extra-spacing-that-i-dont-want

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!