我想要一个网格布局,其中包含两行和它们之间的拆分器。行的最小高度应为80像素。
此代码效果很好:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" MinHeight="80" />
<RowDefinition Height="5" />
<RowDefinition Height="*" MinHeight="80" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="{Binding Path=ActualHeight, RelativeSource={RelativeSource Self}}" />
<GridSplitter Grid.Row="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Background="Red" />
<TextBlock Grid.Row="2" Text="{Binding Path=ActualHeight, RelativeSource={RelativeSource Self}}" />
</Grid>
但我希望顶行有一个自动高度,直到用户使用分割器手动更改它。所以我把代码更改为:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" MinHeight="80" />
<RowDefinition Height="5" />
<RowDefinition Height="*" MinHeight="80" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="{Binding Path=ActualHeight, RelativeSource={RelativeSource Self}}" />
<GridSplitter Grid.Row="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Background="Red" />
<TextBlock Grid.Row="2" Text="{Binding Path=ActualHeight, RelativeSource={RelativeSource Self}}" />
</Grid>
还有一个问题。 Splitter仍然满足行约束,但如果我将分割器拖得太低,它会无限地开始增加顶行的高度。这导致底行完全低于窗口的底部边界。
我在GridSplitter代码上做了一些Reflector,看看如果行有Auto或Star高度,它会使用不同的逻辑。
任何建议如何“修复”它?
答案 0 :(得分:6)
我自己曾经遇到过这个问题。似乎GridSplitter与Auto不兼容。也就是说,我找到了一个潜在的解决方法。
您可以使用“星系数”指定GridLength对象的值。这可以作为相关长度的乘数。
在您的示例中,如果您将要保留的行保留为星号,并将星系数设置为非常大的数字,则该行将占用所有可用空间(强制另一行变为其最小高度) )。虽然这与“auto”的行为不同(第一行的高度不是由其内容高度决定的),但它可能会让你更接近。
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" MinHeight="80" />
<RowDefinition Height="5" />
<RowDefinition Height="10000*" MinHeight="80" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="{Binding Path=ActualHeight, RelativeSource={RelativeSource Self}}" />
<GridSplitter Grid.Row="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Background="Red" />
<TextBlock Grid.Row="2" Text="{Binding Path=ActualHeight, RelativeSource={RelativeSource Self}}" />
</Grid>
答案 1 :(得分:6)
我已针对此问题制定了解决方法。点是在我们拖动拆分器时为顶行设置MaxHeight。代码如下:
public class FixedGridSplitter : GridSplitter
{
private Grid grid;
private RowDefinition definition1;
private double savedMaxLength;
#region static
static FixedGridSplitter()
{
new GridSplitter();
EventManager.RegisterClassHandler(typeof(FixedGridSplitter), Thumb.DragCompletedEvent, new DragCompletedEventHandler(FixedGridSplitter.OnDragCompleted));
EventManager.RegisterClassHandler(typeof(FixedGridSplitter), Thumb.DragStartedEvent, new DragStartedEventHandler(FixedGridSplitter.OnDragStarted));
}
private static void OnDragStarted(object sender, DragStartedEventArgs e)
{
FixedGridSplitter splitter = (FixedGridSplitter)sender;
splitter.OnDragStarted(e);
}
private static void OnDragCompleted(object sender, DragCompletedEventArgs e)
{
FixedGridSplitter splitter = (FixedGridSplitter)sender;
splitter.OnDragCompleted(e);
}
#endregion
private void OnDragStarted(DragStartedEventArgs sender)
{
grid = Parent as Grid;
if (grid == null)
return;
int splitterIndex = (int)GetValue(Grid.RowProperty);
definition1 = grid.RowDefinitions[splitterIndex - 1];
RowDefinition definition2 = grid.RowDefinitions[splitterIndex + 1];
savedMaxLength = definition1.MaxHeight;
double maxHeight = definition1.ActualHeight + definition2.ActualHeight - definition2.MinHeight;
definition1.MaxHeight = maxHeight;
}
private void OnDragCompleted(DragCompletedEventArgs sender)
{
definition1.MaxHeight = savedMaxLength;
grid = null;
definition1 = null;
}
}
然后用FixedGridSplitter替换GridSplitter。
注意:此代码不是通用的 - 它不支持列,并假设底行指定了MinHeight。