Как заставить детей StackPanel заполнять максимальное пространство вниз?

Я просто хочу, чтобы текст текстом слева, а окно справки справа.

Окно справки должно распространяться до конца.

Если вы выберете внешний StackPanel ниже, он отлично работает.

Но по причинам макета (я динамически вставляю UserControls) мне нужно иметь стек StackPanel.

Как мне заставить GroupBox растягиваться до нижней части StackPanel, как вы можете видеть, я пробовал:

  • VerticalAlignment = "Stretch"
  • VerticalContentAlignment = "Stretch"
  • Height = "Авто"

XAML:

<Window x:Class="TestDynamic033.Test3"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Test3" Height="300" Width="600">
    <StackPanel 
        VerticalAlignment="Stretch" 
        Height="Auto">

        <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>
    </StackPanel>
</Window>

Ответ:

Спасибо, Марк, используя DockPanel вместо StackPanel, очистил его. В общем, я все больше и больше использую DockPanel для компоновки WPF, здесь фиксированный XAML:

<Window x:Class="TestDynamic033.Test3"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Test3" Height="300" Width="600" MinWidth="500" MinHeight="200">
    <DockPanel 
        VerticalAlignment="Stretch" 
        Height="Auto">

        <DockPanel 
            HorizontalAlignment="Stretch" 
            VerticalAlignment="Stretch" 
            Height="Auto" 
            MinWidth="400"
            Margin="10">

            <GroupBox 
                DockPanel.Dock="Right" 
                Header="Help" 
                Width="100" 
                VerticalAlignment="Stretch" 
                VerticalContentAlignment="Stretch" 
                Height="Auto">
                <Border CornerRadius="3" Background="Beige">
                    <TextBlock Text="This is the help that is available on the news screen." TextWrapping="Wrap" 

                Padding="5"/>
                </Border>
            </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>
</Window>

Ответ 1

Похоже, вы хотите StackPanel, где последний элемент использует все оставшееся пространство. Но почему бы не использовать DockPanel? Украсьте другие элементы в DockPanel с помощью DockPanel.Dock="Top", а затем ваш элемент управления справки может заполнить оставшееся пространство.

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>

Если вы находитесь на платформе без DockPanel доступных (например, WindowsStore), вы можете создать тот же эффект с сеткой. Здесь приведенный выше пример выполняется с использованием сеток:

<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>

Ответ 2

Причина, по которой это происходит, состоит в том, что панель стека измеряет каждый дочерний элемент с положительной бесконечностью в качестве ограничения для оси, в котором они укладываются. Элементы управления дочерними элементами должны возвращать то, насколько они хотят быть (положительная бесконечность не является действительным возвратом из MeasureOverride в любой оси), поэтому они верните наименьший размер, где все подойдет. У них нет способа узнать, сколько места им действительно нужно заполнить.

Если ваше представление не нуждается в функции прокрутки, а приведенный выше ответ не подходит вашим потребностям, я бы предложил реализовать вашу собственную панель. Вероятно, вы можете получить прямо из StackPanel, а затем все, что вам нужно сделать, это изменить метод ArrangeOverride, чтобы он делит оставшееся пространство между его дочерние элементы (дающие им одинаковое количество дополнительного пространства). Элементы должны отображаться отлично, если им предоставляется больше места, чем они хотели, но если вы дадите им меньше, вы начнете видеть сбои.

Если вы хотите прокрутить все это, я боюсь, что все будет немного сложнее, потому что ScrollViewer дает вам бесконечное пространство для работы, с помощью которого вы будете находиться в том же положении, что и дочерние элементы были изначально. В этой ситуации вы можете создать новое свойство на своей новой панели, которое позволяет указать размер видового экрана, вы должны привязать его к размеру ScrollViewers. В идеале вы бы использовали IScrollInfo, но это начинает усложняться, если вы собираетесь реализовать его все правильно.

Ответ 3

Альтернативным методом является использование Grid с одним столбцом и n строками. Установите все высоты строк на Auto, а нижнюю - на строку 1*.

Я предпочитаю этот метод, потому что нашел, что сетки имеют лучшую производительность компоновки, чем DockPanels, StackPanels и WrapPanels. Но если вы не используете их в ItemTemplate (где макет выполняется для большого количества элементов), вы, вероятно, никогда не заметите.

Ответ 4

Вы можете использовать измененную версию в 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>

Первая кнопка будет заполнена.

Вы можете установить его через Nuget:

Install-Package SpicyTaco.AutoGrid

Я также рекомендую взглянуть на wpf-autogrid. Это очень полезно для форм в WPF вместо DockPanel, StackPanel и Grid и решить проблему с растяжением очень легко и изящно. Просто посмотрите на readme на github.

<st:AutoGrid Columns="160,*" ChildMargin="3">
    <Label Content="Name:"/>
    <TextBox/>

    <Label Content="E-Mail:"/>
    <TextBox/>

    <Label Content="Comment:"/>
    <TextBox/>
</st:AutoGrid>

Ответ 5

Несколько вещей, которые вы могли бы сделать:

1: установить Orientation по вертикали:

<StackPanel Orientation="Vertical"></StackPanel>
  1. Установите Height StackPanel окна:

И, конечно же, вы можете комбинировать эти свойства:

<StackPanel Orientation="Vertical" Height="600"></StackPanel>

Вам не нужно делать кучу дополнительной работы по установке NuGets и еще много чего....

РЕДАКТИРОВАТЬ

Вы также можете разместить StackPanel внутри ScrollViewer. Это позволит вам контролировать высоту GroupBox, не жертвуя видимостью контента.

<GroupBox>
    <ScrollViewer>
        <StackPanel Orientation="Vertical>
              <!-- Place Children Objects here-->
        <StackPanel>
    <ScrollViewer>
<GroupBox>