HorizontalAlignment = Stretch, MaxWidth e Left allineati allo stesso tempo?


95

Sembra che dovrebbe essere facile, ma sono perplesso. In WPF, vorrei un TextBox che si estende fino alla larghezza del suo genitore, ma solo fino a una larghezza massima. Il problema è che voglio che sia lasciato giustificato all'interno del suo genitore. Per farlo allungare devi usare HorizontalAlignment = "Stretch", ma poi il risultato è centrato. Ho sperimentato con HorizontalContentAlignment, ma non sembra fare nulla.

Come faccio a far crescere questa casella di testo blu con le dimensioni della finestra, avere una larghezza massima di 200 pixel e essere giustificata a sinistra?

<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 è il trucco?

Risposte:


89

Puoi impostare HorizontalAlignmenta Sinistra, impostare il tuo MaxWidthe quindi legarlo Widthal ActualWidthdell'elemento genitore:

<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
Non si ridimensiona automaticamente .. Sembra essere adatto al contenuto .. mi manca qualcosa?
Gishu

Questo sembra mandare in crash il mio lettore Silverlight
resopollution

2
@ Gishu, assicurati di impostare HorizontalAlignment="Stretch"l' Container elemento. (ps, mi rendo conto che hai fatto quella domanda più di 6 anni fa.)
David Murdoch

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

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

Penso che sia necessario impostare VerticalAlignment = "Top" per la casella di testo .. sembra essere allungato per impostazione predefinita.
Gishu

1
+1. Bello e pulito. Ogni volta che provo a gestire il layout legandomi a una larghezza effettiva (come nella risposta accettata), le cose si complicano.
Eren Ersönmez

1
Mi sono imbattuto in questa domanda mentre cercavo di risolvere lo stesso problema. Nel mio caso questa è la risposta migliore in quanto funziona in WinRT. L'altra risposta no perché non è possibile eseguire il binding su ActualWidth in WinRT.
Slade

Slade - L'ho appena fatto in un'app di Windows Store: MaxWidth = "{Binding ActualWidth, ElementName = Layout}" e ha funzionato bene per associare MaxWidth a un'altra proprietà ActualWidth degli elementi. Non sono sicuro del motivo per cui questo ha funzionato per me, ma ha fatto quello che mi aspettavo e, come è stato menzionato in precedenza nella risposta che aveva la soluzione di associazione della larghezza, non ha ridimensionato l'elemento quando il genitore è stato ridimensionato a causa dell'ingrandimento della finestra o più piccola.
David Rector

8

Entrambe le risposte fornite hanno funzionato per il problema che ho affermato - Grazie!

Nella mia applicazione reale, però, stavo cercando di vincolare un pannello all'interno di uno ScrollViewer e il metodo di Kent non lo gestiva molto bene per qualche motivo che non mi sono preoccupato di rintracciare. Fondamentalmente i controlli potrebbero espandersi oltre l'impostazione MaxWidth e sconfiggere il mio intento.

La tecnica di Nir ha funzionato bene e non ha avuto problemi con ScrollViewer, anche se c'è una cosa minore a cui prestare attenzione. Vuoi essere sicuro che i margini destro e sinistro sul TextBox siano impostati su 0 o si intrometteranno. Ho anche cambiato l'associazione per utilizzare ViewportWidth invece di ActualWidth per evitare problemi quando appariva la barra di scorrimento verticale.


6

Puoi usarlo per la larghezza del tuo DataTemplate:

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

Assicurati che la tua radice DataTemplate abbia Margin = "0" (puoi usare un pannello come root e impostare Margin sui figli di quella radice)


1

Funzionalmente simile alla risposta accettata, ma non richiede la specifica dell'elemento genitore:

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

1

Forse posso ancora aiutare qualcuno che si imbatte in questa domanda, perché questo è un problema molto vecchio.

Anche io avevo bisogno di questo e ho scritto un comportamento per prendermene cura. Quindi ecco il 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;
            }
        }
    }
}

Quindi puoi usarlo in questo modo:

<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 infine dimenticare di utilizzare lo System.Windows.Interactivityspazio dei nomi per utilizzare il comportamento.


0

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

Nel mio caso ho dovuto mettere la casella di testo in un pannello a pila per allungare la casella di testo sul lato sinistro. Grazie al post precedente. Solo per un esempio ho impostato un colore di sfondo per vedere cosa succede quando le dimensioni della finestra cambiano.

<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>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.