Como conseguir que as crianças StackPanel para preencher o espaço máximo para baixo?
-
05-09-2019 - |
Pergunta
Eu simplesmente quero texto que flui do lado esquerdo, e uma caixa de ajuda à direita.
A caixa de ajuda deve se estender por todo o caminho até o fundo.
Se você tirar o StackPanel exterior abaixo ele funciona muito bem.
Mas, por razões de disposição (Eu estou inserindo UserControls dinamicamente) Eu preciso ter o envolvimento de StackPanel.
Como faço para obter o GroupBox para estender até o fundo do StackPanel, como você pode ver que eu tentei:
- 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>
Resposta:
Graças Mark, usando DockPanel vez de StackPanel limpou-lo. Em geral, eu me encontrar usando DockPanel mais e mais agora para WPF layouting, aqui está o XAML fixo:
<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>
Solução
Parece que você quer um StackPanel
onde o elemento final usa todo o espaço restante. Mas por que não usar um DockPanel
? Decore os outros elementos do DockPanel
com DockPanel.Dock="Top"
, e, em seguida, seu controle ajuda pode preencher o espaço restante.
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>
Se você estiver em uma plataforma sem DockPanel
disponível (por exemplo Windows Store), você pode criar o mesmo efeito com uma grade. Aqui está o exemplo acima realizada utilizando grades em vez disso:
<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>
Outras dicas
A razão por que isso está acontecendo é porque o painel de pilha mede cada elemento filho com o infinito positivo como a restrição para o eixo que está empilhando elementos ao longo. Os controles filho tem que devolver o quão grande eles querem ser (infinito positivo não é um retorno válido a partir da MeasureOverride em qualquer eixo) para que eles retornam o menor tamanho, onde tudo vai se encaixar. Eles têm nenhuma maneira de saber quanto espaço eles realmente têm de preencher.
Se a sua visão não precisa ter um recurso de rolagem e a resposta acima não atender às suas necessidades, gostaria de sugerir implementar seu próprio painel. Você provavelmente pode derivar em linha reta do StackPanel e depois tudo o que você precisa fazer é mudar o método ArrangeOverride para que ele divide o espaço restante entre seus elementos filho (dando-lhes cada a mesma quantidade de espaço extra). Elementos devem tornar bem se forem dadas mais espaço do que eles queriam, mas se você dar-lhes menos que você vai começar a ver falhas.
Se você quer ser capaz de rolar a coisa toda, então eu tenho coisas com medo será um pouco mais difícil, porque o ScrollViewer dá-lhe uma quantidade infinita de espaço para trabalho com o qual irá colocá-lo na mesma posição que o elementos filhos eram originalmente. Nessa situação, você pode querer criar uma nova propriedade em seu novo painel que permite especificar o tamanho da janela, você deve ser capaz de ligar este ao tamanho do ScrollViewer. O ideal seria implementar IScrollInfo , mas que começa a ficar complicado se você estiver indo para implementar tudo isso corretamente.
Um método alternativo é a utilização de uma grade com uma coluna e n linhas. Definir todas as linhas alturas para Auto
, eo mais inferior altura da linha para 1*
.
Eu prefiro este método porque eu encontrei Grids ter um desempenho melhor do que o layout DockPanels, StackPanels e WrapPanels. Mas se você estiver usando-os em um ItemTemplate (onde o layout está sendo realizada por um grande número de itens), você provavelmente nunca aviso prévio.
Você pode usar versão modificada do 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>
O primeiro botão será de preenchimento.
Você pode instalá-lo via Nuget:
Install-Package SpicyTaco.AutoGrid
Eu também recomendo dar uma olhada WPF-AutoGrid . É muito útil para formulários em WPF em vez de DockPanel, StackPanel e Grade e resolver o problema com alongamento muito fácil e graciosamente. Basta olhar para leia-me no github.
<st:AutoGrid Columns="160,*" ChildMargin="3">
<Label Content="Name:"/>
<TextBox/>
<Label Content="E-Mail:"/>
<TextBox/>
<Label Content="Comment:"/>
<TextBox/>
</st:AutoGrid>
Algumas coisas que você poderia fazer:
1: Defina o Orientation
para Vertical :
<StackPanel Orientation="Vertical"></StackPanel>
-
Defina a
Height
doStackPanel
a mesma que a da janela:
E, claro, você pode combinar os Propriedades :
<StackPanel Orientation="Vertical" Height="600"></StackPanel>
Você não precisa fazer um monte de trabalho extra com a instalação nugets e outros enfeites ....
Editar
Você também pode colocar o interior StackPanel de um ScrollViewer. Isso permitirá que você para controlar a altura do GroupBox sem sacrificar a visibilidade do conteúdo.
<GroupBox>
<ScrollViewer>
<StackPanel Orientation="Vertical>
<!-- Place Children Objects here-->
<StackPanel>
<ScrollViewer>
<GroupBox>