Как получить детей элемента StackPanel, чтобы заполнить максимальное пространство вниз?


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

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

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

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

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

  • VerticalAlignment= "Stretch"
  • VerticalContentAlignment= "Stretch"
  • Высота="Авто"

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 301

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 до вертикальный:

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