How to get StackPanel's children to fill maximum space downward?

后端 未结 4 1694
天涯浪人
天涯浪人 2020-11-28 00:41

I simply want flowing text on the left, and a help box on the right.

The help box should extend all the way to the bottom.

If you take out the outer St

相关标签:
4条回答
  • 2020-11-28 01:03

    The reason that this is happening is because the stack panel measures every child element with positive infinity as the constraint for the axis that it is stacking elements along. The child controls have to return how big they want to be (positive infinity is not a valid return from the MeasureOverride in either axis) so they return the smallest size where everything will fit. They have no way of knowing how much space they really have to fill.

    If your view doesn’t need to have a scrolling feature and the answer above doesn't suit your needs, I would suggest implement your own panel. You can probably derive straight from StackPanel and then all you will need to do is change the ArrangeOverride method so that it divides the remaining space up between its child elements (giving them each the same amount of extra space). Elements should render fine if they are given more space than they wanted, but if you give them less you will start to see glitches.

    If you want to be able to scroll the whole thing then I am afraid things will be quite a bit more difficult, because the ScrollViewer gives you an infinite amount of space to work with which will put you in the same position as the child elements were originally. In this situation you might want to create a new property on your new panel which lets you specify the viewport size, you should be able to bind this to the ScrollViewer’s size. Ideally you would implement IScrollInfo, but that starts to get complicated if you are going to implement all of it properly.

    0 讨论(0)
  • 2020-11-28 01:06

    It sounds like you want a StackPanel where the final element uses up all the remaining space. But why not use a DockPanel? Decorate the other elements in the DockPanel with DockPanel.Dock="Top", and then your help control can fill the remaining space.

    XAML:

    <DockPanel Width="200" Height="200" Background="PowderBlue">
        <TextBlock DockPanel.Dock="Top">Something</TextBlock>
        <TextBlock DockPanel.Dock="Top">Something else</TextBlock>
        <DockPanel
            HorizontalAlignment="Stretch" 
            VerticalAlignment="Stretch" 
            Height="Auto" 
            Margin="10">
    
          <GroupBox 
            DockPanel.Dock="Right" 
            Header="Help" 
            Width="100" 
            Background="Beige" 
            VerticalAlignment="Stretch" 
            VerticalContentAlignment="Stretch" 
            Height="Auto">
            <TextBlock Text="This is the help that is available on the news screen." 
                       TextWrapping="Wrap" />
         </GroupBox>
    
          <StackPanel DockPanel.Dock="Left" Margin="10" 
               Width="Auto" HorizontalAlignment="Stretch">
              <TextBlock Text="Here is the news that should wrap around." 
                         TextWrapping="Wrap"/>
          </StackPanel>
        </DockPanel>
    </DockPanel>
    

    If you are on a platform without DockPanel available (e.g. WindowsStore), you can create the same effect with a grid. Here's the above example accomplished using grids instead:

    <Grid Width="200" Height="200" Background="PowderBlue">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <StackPanel Grid.Row="0">
            <TextBlock>Something</TextBlock>
            <TextBlock>Something else</TextBlock>
        </StackPanel>
        <Grid Height="Auto" Grid.Row="1" Margin="10">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="100"/>
            </Grid.ColumnDefinitions>
            <GroupBox
                Width="100"
                Height="Auto"
                Grid.Column="1"
                Background="Beige"
                Header="Help">
                <TextBlock Text="This is the help that is available on the news screen." 
                  TextWrapping="Wrap"/>
            </GroupBox>
            <StackPanel Width="Auto" Margin="10" DockPanel.Dock="Left">
                <TextBlock Text="Here is the news that should wrap around." 
                  TextWrapping="Wrap"/>
            </StackPanel>
        </Grid>
    </Grid>
    
    0 讨论(0)
  • 2020-11-28 01:14

    You can use SpicyTaco.AutoGrid - a modified version of StackPanel:

    <st:StackPanel Orientation="Horizontal" MarginBetweenChildren="10" Margin="10">
       <Button Content="Info" HorizontalAlignment="Left" st:StackPanel.Fill="Fill"/>
       <Button Content="Cancel"/>
       <Button Content="Save"/>
    </st:StackPanel>
    

    First button will be fill.

    You can install it via NuGet:

    Install-Package SpicyTaco.AutoGrid
    

    I recommend taking a look at SpicyTaco.AutoGrid. It's very useful for forms in WPF instead of DockPanel, StackPanel and Grid and solve problem with stretching very easy and gracefully. Just look at readme on GitHub.

    <st:AutoGrid Columns="160,*" ChildMargin="3">
        <Label Content="Name:"/>
        <TextBox/>
    
        <Label Content="E-Mail:"/>
        <TextBox/>
    
        <Label Content="Comment:"/>
        <TextBox/>
    </st:AutoGrid>
    
    0 讨论(0)
  • 2020-11-28 01:27

    An alternative method is to use a Grid with one column and n rows. Set all the rows heights to Auto, and the bottom-most row height to 1*.

    I prefer this method because I've found Grids have better layout performance than DockPanels, StackPanels, and WrapPanels. But unless you're using them in an ItemTemplate (where the layout is being performed for a large number of items), you'll probably never notice.

    0 讨论(0)
提交回复
热议问题