HorizontalAlignment = Stretch, MaxWidth e Left alinhado ao mesmo tempo?

95

Parece que deveria ser fácil, mas estou perplexo. No WPF, eu gostaria de um TextBox que se estendesse até a largura de seu pai, mas apenas até a largura máxima. O problema é que quero que seja justificado à esquerda em seu pai. Para esticar, você deve usar HorizontalAlignment = "Stretch", mas o resultado é centralizado. Eu experimentei o HorizontalContentAlignment, mas ele não parece fazer nada.

Como faço para que esta caixa de texto azul cresça com o tamanho da janela, tenha uma largura máxima de 200 pixels e seja justificada à esquerda?

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <StackPanel>  
    <TextBox Background="Azure" Text="Hello" HorizontalAlignment="Stretch" MaxWidth="200" />
  </StackPanel>
</Page>

Qual é o truque?

Scott Bussinger
fonte

Respostas:

89

Você pode definir HorizontalAlignmentcomo Esquerda, definir seu MaxWidthe vincular Widthao do ActualWidthelemento pai:

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <StackPanel Name="Container">   
    <TextBox Background="Azure" 
    Width="{Binding ElementName=Container,Path=ActualWidth}"
    Text="Hello" HorizontalAlignment="Left" MaxWidth="200" />
  </StackPanel>
</Page>
Nir
fonte
7
Não é redimensionado automaticamente .. Parece ser adequado ao conteúdo .. estou faltando alguma coisa?
Gishu
Isso parece travar meu player silverlight
resopoluição em
2
@Gishu, certifique-se de definir HorizontalAlignment="Stretch"no Container elemento. (ps, eu sei que você fez essa pergunta há mais de 6 anos.)
David Murdoch,
50
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" MaxWidth="200"/>
    </Grid.ColumnDefinitions>

    <TextBox Background="Azure" Text="Hello" />
</Grid>
Kent Boogaart
fonte
Eu acho que você precisa definir VerticalAlignment = "Top" para a caixa de texto .. parece ser esticado por padrão.
Gishu
1
+1. Legal e Limpo. Sempre que tento gerenciar o layout vinculando-o a alguma largura real (como na resposta aceita), as coisas ficam complicadas.
Eren Ersönmez
1
Acabei de me deparar com essa pergunta enquanto tentava resolver o mesmo problema. No meu caso, esta é a melhor resposta, pois funciona no WinRT. A outra resposta não, porque você não pode vincular a ActualWidth no WinRT.
Slade
Slade - Acabei de fazer isso em um aplicativo da Windows Store: MaxWidth = "{Binding ActualWidth, ElementName = Layout}" e funcionou bem para vincular MaxWidth a outra propriedade ActualWidth dos elementos. Não sei por que isso funcionou para mim, mas fez o que eu esperava e, como foi mencionado anteriormente na resposta que tinha a solução de ligação de largura, não redimensionou o elemento quando o pai foi redimensionado devido ao aumento da janela ou menor.
David Rector
8

Ambas as respostas fornecidas funcionaram para o problema que declarei - Obrigado!

Em meu aplicativo real, porém, eu estava tentando restringir um painel dentro de um ScrollViewer e o método de Kent não lidou com isso muito bem por algum motivo que não me preocupei em rastrear. Basicamente, os controles poderiam se expandir além da configuração MaxWidth e anular minha intenção.

A técnica de Nir funcionou bem e não teve problemas com o ScrollViewer, embora haja uma coisa menor a ser observada. Você quer ter certeza de que as margens direita e esquerda no TextBox estão definidas como 0 ou elas ficarão no caminho. Eu também alterei a ligação para usar ViewportWidth em vez de ActualWidth para evitar problemas quando a barra de rolagem vertical apareceu.

Scott Bussinger
fonte
6

Você pode usar isso para a largura do seu DataTemplate:

Width="{Binding ActualWidth,RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ScrollContentPresenter}}}"

Certifique-se de que sua raiz DataTemplate tenha Margin = "0" (você pode usar algum painel como a raiz e definir a margem para os filhos dessa raiz)

Filip Skakun
fonte
1

Funcionalmente semelhante à resposta aceita, mas não exige que o elemento pai seja especificado:

<TextBox
    Width="{Binding ActualWidth, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type FrameworkElement}}}"
    MaxWidth="500"
    HorizontalAlignment="Left" />
maxp
fonte
1

Talvez eu ainda possa ajudar alguém que se depara com essa questão, porque esse é um problema muito antigo.

Eu também precisava disso e escrevi um comportamento para cuidar disso. Então aqui está o comportamento:

public class StretchMaxWidthBehavior : Behavior<FrameworkElement>
{        
    protected override void OnAttached()
    {
        base.OnAttached();
        ((FrameworkElement)this.AssociatedObject.Parent).SizeChanged += this.OnSizeChanged;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        ((FrameworkElement)this.AssociatedObject.Parent).SizeChanged -= this.OnSizeChanged;
    }

    private void OnSizeChanged(object sender, SizeChangedEventArgs e)
    {
        this.SetAlignments();
    }

    private void SetAlignments()
    {
        var slot = LayoutInformation.GetLayoutSlot(this.AssociatedObject);
        var newWidth = slot.Width;
        var newHeight = slot.Height;

        if (!double.IsInfinity(this.AssociatedObject.MaxWidth))
        {
            if (this.AssociatedObject.MaxWidth < newWidth)
            {
                this.AssociatedObject.HorizontalAlignment = HorizontalAlignment.Left;
                this.AssociatedObject.Width = this.AssociatedObject.MaxWidth;
            }
            else
            {
                this.AssociatedObject.HorizontalAlignment = HorizontalAlignment.Stretch;
                this.AssociatedObject.Width = double.NaN;
            }
        }

        if (!double.IsInfinity(this.AssociatedObject.MaxHeight))
        {
            if (this.AssociatedObject.MaxHeight < newHeight)
            {
                this.AssociatedObject.VerticalAlignment = VerticalAlignment.Top;
                this.AssociatedObject.Height = this.AssociatedObject.MaxHeight;
            }
            else
            {
                this.AssociatedObject.VerticalAlignment = VerticalAlignment.Stretch;
                this.AssociatedObject.Height = double.NaN;
            }
        }
    }
}

Então você pode usá-lo assim:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>

    <TextBlock Grid.Column="0" Text="Label" />
    <TextBox Grid.Column="1" MaxWidth="600">
          <i:Interaction.Behaviors>                       
               <cbh:StretchMaxWidthBehavior/>
          </i:Interaction.Behaviors>
    </TextBox>
</Grid>

E, finalmente, esquecer de usar o System.Windows.Interactivitynamespace para usar o comportamento.

YC
fonte
0

eu usaria SharedSizeGroup

<Grid>
    <Grid.ColumnDefinition>
        <ColumnDefinition SharedSizeGroup="col1"></ColumnDefinition>  
        <ColumnDefinition SharedSizeGroup="col2"></ColumnDefinition>
    </Grid.ColumnDefinition>
    <TextBox Background="Azure" Text="Hello" Grid.Column="1" MaxWidth="200" />
</Grid>
Patrick Cairns
fonte
0

No meu caso, tive que colocar a caixa de texto em um painel de pilha para esticar a caixa de texto no lado esquerdo. Graças ao post anterior. Apenas como exemplo, eu defini uma cor de fundo para ver o que acontece quando o tamanho da janela está mudando.

<StackPanel Name="JustContainer" VerticalAlignment="Center" HorizontalAlignment="Stretch" Background="BlueViolet" >
    <TextBox 
       Name="Input" Text="Hello World" 
       MaxWidth="300"
       HorizontalAlignment="Right"
       Width="{Binding ActualWidth, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type FrameworkElement}}}">
    </TextBox>
</StackPanel>
poupou
fonte