HorizontalAlignment = Estirar, MaxWidth e Izquierda alineados al mismo tiempo?


95

Parece que debería ser fácil, pero estoy perplejo. En WPF, me gustaría un TextBox que se extienda hasta el ancho de su padre, pero solo hasta un ancho máximo. El problema es que quiero que quede justificado a la izquierda dentro de su padre. Para conseguir que se estire tienes que usar HorizontalAlignment = "Stretch", pero luego el resultado está centrado. He experimentado con HorizontalContentAlignment, pero no parece hacer nada.

¿Cómo hago para que este cuadro de texto azul crezca con el tamaño de la ventana, tenga un ancho máximo de 200 píxeles y se justifique a la izquierda?

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

¿Cuál es el truco?

Respuestas:


89

Puede establecerlo HorizontalAlignmenten Izquierda, establecer su MaxWidthy luego enlazar Widthal del ActualWidthelemento padre:

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

7
No se ajusta automáticamente al tamaño. Parece que se ajusta al contenido. ¿Me estoy perdiendo algo?
Gishu

Esto parece bloquear mi reproductor
Silverlight

2
@Gishu, asegúrate de configurar HorizontalAlignment="Stretch"el Container elemento. (PD, me doy cuenta de que hizo esa pregunta hace más de 6 años.)
David Murdoch

50
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" MaxWidth="200"/>
    </Grid.ColumnDefinitions>

    <TextBox Background="Azure" Text="Hello" />
</Grid>

Creo que necesitas establecer VerticalAlignment = "Top" para el cuadro de texto ... parece ser estirado por defecto.
Gishu

1
+1. Bonito y limpio. Cada vez que trato de administrar el diseño enlazando a un ancho real (como en la respuesta aceptada), las cosas se complican.
Eren Ersönmez

1
Me encontré con esta pregunta mientras intentaba resolver el mismo problema. En mi caso, esta es la mejor respuesta, ya que funciona en WinRT. La otra respuesta no lo hace porque no puede enlazar en ActualWidth en WinRT.
Slade

Slade - Acabo de hacer esto en una aplicación de la Tienda Windows: MaxWidth = "{Binding ActualWidth, ElementName = Layout}" y funcionó bien para vincular MaxWidth a la propiedad ActualWidth de otros elementos. No estoy seguro de por qué esto funcionó para mí, pero hizo lo que esperaba, y como se mencionó anteriormente en la respuesta que tenía la solución de enlace de ancho, no cambió el tamaño del elemento cuando el padre cambió el tamaño debido a que hizo que la ventana fuera más grande o menor.
David Rector

8

Ambas respuestas funcionaron para el problema que dije: ¡Gracias!

Sin embargo, en mi aplicación real, estaba tratando de restringir un panel dentro de un ScrollViewer y el método de Kent no manejó eso muy bien por alguna razón que no me molesté en rastrear. Básicamente, los controles podrían expandirse más allá de la configuración de MaxWidth y derrotaron mi intención.

La técnica de Nir funcionó bien y no tuvo el problema con ScrollViewer, aunque hay una pequeña cosa a tener en cuenta. Desea asegurarse de que los márgenes derecho e izquierdo del TextBox estén configurados en 0 o se interpondrán en el camino. También cambié el enlace para usar ViewportWidth en lugar de ActualWidth para evitar problemas cuando apareció la barra de desplazamiento vertical.


6

Puede usar esto para el Ancho de su DataTemplate:

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

Asegúrese de que su raíz de DataTemplate tenga Margin = "0" (puede usar algún panel como raíz y establecer el Margen para los hijos de esa raíz)


1

Funcionalmente similar a la respuesta aceptada, pero no requiere que se especifique el elemento principal:

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

1

Quizás todavía pueda ayudar a alguien que se encuentre con esta pregunta, porque este es un tema muy antiguo.

Yo también necesitaba esto y escribí un comportamiento para solucionarlo. Entonces aquí está el comportamiento:

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

Entonces puedes usarlo así:

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

Y finalmente olvidar usar el System.Windows.Interactivityespacio de nombres para usar el comportamiento.


0

yo usaría 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>

0

En mi caso, tuve que poner el cuadro de texto en un panel de pila para estirar el cuadro de texto en el lado izquierdo. Gracias a la publicación anterior. Solo por ejemplo, configuré un color de fondo para ver qué sucede cuando cambia el tamaño de la ventana.

<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>
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.