WPF StackPanel vertical Frame full height

2019-02-17 11:35发布

问题:

I need to fill empty space with last element in stackpanel (Frame):

    <DockPanel>
        <StackPanel Orientation="Vertical">
            <Frame NavigationUIVisibility="Hidden" Height="100" x:Name="_menu" />
            <Frame NavigationUIVisibility="Hidden" x:Name="_mainFrame" />
        </StackPanel>
    </DockPanel>

_mainFrame - fill empty space from _menu Frame to the bottom

回答1:

StackPanel is not the layout container for allowing elements to "fill remaining space". StackPanel has a specific purpose among other layout containers. it's to "Stack" items vertically/horizontally and works based on it's children's desired height than what's available. It will allow it's children to get how much ever space they desire.

For your requirement, you'd want to go with either a DockPanel/Grid. Both of these controls would allow the parent container to "limit" it's children's dimension based on what's available.

In your example you already have a DockPanel. However you've put a StackPanel as it's child and it's the only child which doesn't make much sense. You want to try and use a layout container when you have more than 1 child item to put into a layout. In this case the StackPanel is the only child of the DockPanel.

To get your requirement by using a DockPanel, you could go with,

<DockPanel>
    <Frame NavigationUIVisibility="Hidden" Height="100" x:Name="_menu" DockPanel.Dock="Top" />
    <Frame NavigationUIVisibility="Hidden" x:Name="_mainFrame" />
</DockPanel>

DockPanel by default uses LastChildFill="True" thus the second item in the declaration will be stretched to fill remaining space available which is what you need. If you set this property to false, it wouldn't stretch it.

To do the same thing with a Grid:

<Grid>
  <Grid.RowDefinitions>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="*"/>
  </Grid.RowDefinitions>
  <Frame NavigationUIVisibility="Hidden" Height="100" x:Name="_menu" />
  <Frame NavigationUIVisibility="Hidden" x:Name="_mainFrame" Grid.Row="1" />
</Grid>

for your requirement, I'd prefer to go with the DockPanel, the Grid method is just something good to be aware about and probably use when the situation demands it.