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

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

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

Если вы вытащите внешнюю панель StackPanel ниже, она отлично работает.

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

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

  • VerticalAlignment= "Растяжка"
  • VerticalContentAlignment="Стрейч"
  • Высота="Авто"

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>

5 ответов


похоже, вы хотите 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>

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

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

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


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

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


можно использовать модифицированная версия для 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>

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

1: задание Orientation to вертикальный:

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