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


356

Я просто хочу текти текст ліворуч і прапорець справа.

Довідкова скринька повинна поширюватися до самого низу.

Якщо ви виймаєте зовнішню сторону StackPanelвнизу, це чудово працює.

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

Як я можу GroupBoxрозширити донизу StackPanel, як ви бачите, я намагався:

  • VerticalAlignment="Stretch"
  • VerticalContentAlignment="Stretch"
  • 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>

Виправлено форматування - йому не подобається переходити зі списку до коду
Грег,

1
Чи можете ви зробити розтяжку GroupBox самостійно? Якщо так, почніть додавати батьківські елементи по одному, поки не з’ясуєте, який з них порушує макет.
Дрю Ноакс

RoBorg: приємно знати, що мене здивувало, дякую
Едвард Тангуай

1
Дякую. Використовуючи вашу відповідь, я зміг використовувати 2 вкладені DockPanels для вирішення моєї дуже подібної проблеми!
Ябларго

Відповіді:


344

Це здається, що ви хочете, StackPanelде кінцевий елемент використовує весь залишковий простір. Але чому б не використовувати a 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>

18
Блискуче! Я провів останню годину, намагаючись зрозуміти, як змусити StackPanel зробити це. Відтепер я спочатку шукаю тут свою інформацію про WPF (та інші).
paxdiablo

7
Я не можу повірити, скільки часу я витратив, намагаючись заставити StackPanels робити те, що хотів. Дякую, що поділились! Док-панелі - це те, чого я хотів весь час.
danglund

Докпанелі для планшетів немає. telerik.com/forums/following-blog-post-and-comparison
JP Hellemons

1
Немає док-панелі для додатків Windows Store.
Теоман шипахі

Тепер все про універсальний додаток, а універсальні додатки ще не підтримують DockPanel?
yonexbat

105

Причина цього відбувається в тому, що панель стеків вимірює кожен дочірній елемент з позитивною нескінченністю як обмеження для осі, по якій він укладає елементи. Дочірнє управління повинно повернути те, наскільки вони хочуть бути (позитивна нескінченність не є дійсним поверненням від MeasureOverride в будь-якій осі), тому вони повертають найменший розмір, де все поміститься. Вони не можуть дізнатися, скільки місця їм насправді належить заповнити.

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

Якщо ви хочете мати змогу прокручувати всю справу, то, боюся, все буде дещо складніше, тому що ScrollViewer надає вам нескінченну кількість місця для роботи, з якою ви поставите в таке ж становище, як і дочірні елементи. спочатку. У цій ситуації ви, можливо, захочете створити нову властивість на своїй новій панелі, яка дозволяє задавати розмір вікна перегляду, ви повинні мати можливість прив’язати це до розміру ScrollViewer. В ідеалі ви б реалізували IScrollInfo , але це починає ускладнюватися, якщо ви збираєтеся реалізувати все належним чином.


+1, я б дав вам більше, але дозволено лише 1, ваш перший абзац вказав на те, що численні сторінки Microsoft не змогли, а саме чому нескінченність може виникати як висота / ширина, і той факт, що ви не можете розраховувати на повернення наявного розміру від MeasureOverride .
Айдан

StackPanel всередині Grid вирішує його досить поширену потребу з великою легкістю. Нижній біт при необхідності можна помістити всередині ScrollViewer. Я займаюся WPF з 2006 року і мені лише один раз доводилося робити спеціальні панелі. Я не думаю, що це гарна ідея заохочувати зайву складність.
Кріс Бордеман

@ChrisBordeman Я не впевнений, що розумію, як панель стеків всередині сітки вирішує проблему. Ідея полягає в тому, щоб один або декілька дочірніх елементів на панелі стеку розтягувались, щоб заповнити наявний простір. Якщо розмістити панель стека всередині сітки, це не змушує це робити це?
Калеб Vear

61

Альтернативний метод - використання сітки з одним стовпцем і n рядками. Встановіть всі висоти рядків на Auto, а найнижчу висоту рядка - на 1*.

Я вважаю за краще цей метод, оскільки я виявив, що сітки мають кращу ефективність компонування, ніж DockPanels, StackPanels і WrapPanels. Але якщо ви не використовуєте їх у ItemTemplate (де компонування виконується для великої кількості елементів), ви, ймовірно, ніколи не помітите.


1
для мене найкраще рішення. з цим можна визначити більше одного зростаючого ряду
niyou

18

Ви можете використовувати SpicyTaco.AutoGrid - модифіковану версію 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

Рекомендую поглянути на SpicyTaco.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>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.