Как заставить детей StackPanel заполнить максимальное пространство вниз? - PullRequest
324 голосов
/ 20 февраля 2009

Мне просто нужен текущий текст слева, а справа окно справки.

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

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

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

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

  • VerticalAlignment = "Растянуть"
  • VerticalContentAlignment = "Растянуть"
  • Height = "Auto"

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 ]

311 голосов
/ 20 февраля 2009

Звучит так, как будто вы хотите 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>
100 голосов
/ 20 февраля 2009

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

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

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

55 голосов
/ 20 февраля 2009

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

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

14 голосов
/ 11 марта 2016

Вы можете использовать модифицированную версию 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>
0 голосов
/ 05 декабря 2016

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

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

<StackPanel Orientation="Vertical"></StackPanel>
  1. Установите Height для StackPanel равным значению окна:

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

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

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

EDIT

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

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