我使用嵌套的网格在WPF应用程序中创建了一个稍大的输入表单。我正在使用VS2010和VS2012 Ultimate。
以下是代码:
<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>
我从项目中提取了它并删除了指向我的项目命名空间的所有事件处理程序和绑定,因此您可以将其粘贴到新的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"/><!-- 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>
这没有任何明显的问题。
答案 0 :(得分:1)
我正在使用您的代码进行测试并注意到一些奇怪的行为。您的面板应该像这样呈现:
--------------- | 1 | | --------| 3 | | 2 | | --------------- | 4 | ---------------
但他们目前正在这样渲染,并在2和3单元格的底部添加了额外的空间。
--------------- | 1 | | --------| 3 | | 2 | | | | | --------------- | 4 | ---------------
由于某种原因,在单元格#3中添加的元素通过在底部添加额外的空间来扩展单元格高度。
奇怪的是,我发现这只发生在你的单元格#3的RowSpan
设置为奇数时。如果你将它设置为2或4,它似乎渲染得很好。
<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>
删除单元格#3中的大多数元素正确地将单元格绘制到正确的高度,减少#3中的元素数量会缩小高度,但不会消除它,所以它可能与计算保证金或填充?
所以我的建议是将RowSpan = 2作为第一个示例,或者更改面板布局,使其如下所示:
<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>
<击> 撞击>
<击> Grid
旨在让孩子尽可能填充所有可用空间。
您在所有行上设置Height="Auto"
,这意味着默认情况下,行只会占用渲染其控件所需的空间量。但是,由于Grid
的工作方式,它会尝试拉伸至少其中一行来填充所有可用空间。
通常,此拉伸均匀完成,所有行都会分配相等数量的额外空间,如您在“设计时间”窗口中所示。但是因为你的第二列只有两个对象,一个有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="*"/> <!-- 5th row to take up all available space -->
</Grid.RowDefinitions>
或切换到不具有此行为的其他Panel
,例如DockPanel
LastChildFill="False"
或StackPanel
<击> 撞击>