问题
How can I set up a WPF control to fill the available space in its parent's container, but not expand the parent?
The following snippet describes the layout I am attempting. I would like the Grid
to stretch to accommodate the Expander
, and I would like the ListBox
only to fill the Grid
. I want the ListBox
's scroll bar to appear when the Grid
is too small to show all the ListBoxItem
s.
<ScrollViewer>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<ListBox Grid.Row="0" Grid.Column="0" />
<Expander Grid.Row="0" Grid.Column="1" Header="Expander" />
</Grid>
</ScrollViewer>
Currently what happens is that the Grid
stretches to fit the entire ListBox
, and the outer ScrollViewer
's vertical scroll bar appears. I only want the outer scroll bar to appear when the Expander
gets too big to fit on screen.
回答1:
To solve the same problem I wrote special container class:
class FrugalContainer : Decorator
{
protected override Size MeasureOverride(Size availableSize)
{
return new Size(0, 0);
}
protected override Size ArrangeOverride(Size arrangeSize)
{
// get it all
Child.Measure(arrangeSize);
Child.Arrange(new Rect(arrangeSize));
return Child.RenderSize;
}
}
Surround your ListBox by the container and the height of ListBox will be the same as of Expander.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<FrugalContainer Grid.Row="0" Grid.Column="0" >
<ListBox />
</FrugalContainer>
<Expander Grid.Row="0" Grid.Column="1" Header="Expander" />
</Grid>
Note that I remove Width="Auto"
from column's definition because the FrugalContainer will be as small as it can. So you can't set the width or height of the parent grid's cell to Auto.
If you need autosizing, rewrite the container:
class FrugalHeightContainer : Decorator
{
protected override Size MeasureOverride(Size availableSize)
{
Child.Measure(availableSize);
return new Size(Child.DesiredSize.Width, 0);
}
protected override Size ArrangeOverride(Size arrangeSize)
{
Child.Measure(arrangeSize);
Child.Arrange(new Rect(arrangeSize));
return Child.RenderSize;
}
}
回答2:
What is the point of the ScrollViewer
? Just let the ScrollViewer
in the ListBox
template appear naturally when too little room is available.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<ListBox Grid.Row="0" Grid.Column="0" />
<Expander Grid.Row="0" Grid.Column="1" Header="Expander" />
</Grid>
来源:https://stackoverflow.com/questions/1312043/setting-a-wpf-control-to-expand-to-fill-available-space-and-no-more