Как заставить детей 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>

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, но это становится сложным, если вы собираетесь реализовать все это правильно.

Альтернативный метод - использовать Grid с одним столбцом и 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 по вертикали:

<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>
Другие вопросы по тегам