HorizontalAlignment = Stretch, MaxWidth et Left alignés en même temps?

95

Cela semble être facile mais je suis perplexe. Dans WPF, j'aimerais une zone de texte qui s'étend à la largeur de son parent, mais seulement à une largeur maximale. Le problème est que je veux qu'il reste justifié au sein de son parent. Pour l'étirer, vous devez utiliser HorizontalAlignment = "Stretch", mais le résultat est alors centré. J'ai expérimenté avec HorizontalContentAlignment, mais cela ne semble rien faire.

Comment faire en sorte que cette zone de texte bleue s'agrandisse avec la taille de la fenêtre, qu'elle ait une largeur maximale de 200 pixels et qu'elle soit justifiée à gauche?

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

C'est quoi le truc?

Scott Bussinger
la source

Réponses:

89

Vous pouvez définir HorizontalAlignmentà gauche, définir votre MaxWidth, puis lier Widthà l' ActualWidthélément parent:

<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
la source
7
La redimensionnement automatique ne fonctionne pas. Semble être adapté au contenu. Est-ce que je manque quelque chose?
Gishu
Cela semble planter mon lecteur
Silverlight
2
@Gishu, assurez-vous de définir HorizontalAlignment="Stretch"l' Container élément. (ps, je réalise que vous avez posé cette question il y a plus de 6 ans.)
David Murdoch
51
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" MaxWidth="200"/>
    </Grid.ColumnDefinitions>

    <TextBox Background="Azure" Text="Hello" />
</Grid>
Kent Boogaart
la source
Je pense que vous devez définir VerticalAlignment = "Top" pour la zone de texte .. semble être extensible par défaut.
Gishu
1
+1. Agréable et propre. Chaque fois que j'essaye de gérer la mise en page en liant à une certaine largeur réelle (comme dans la réponse acceptée), les choses se compliquent.
Eren Ersönmez
1
Je viens de tomber sur cette question en essayant de résoudre le même problème. Dans mon cas, c'est la meilleure réponse car cela fonctionne dans WinRT. L'autre réponse n'est pas parce que vous ne pouvez pas lier sur ActualWidth dans WinRT.
Slade
Slade - Je viens de faire cela dans une application Windows Store: MaxWidth = "{Binding ActualWidth, ElementName = Layout}" et cela a bien fonctionné pour lier MaxWidth à une autre propriété ActualWidth d'éléments. Je ne sais pas pourquoi cela a fonctionné pour moi, mais cela a fait ce à quoi je m'attendais, et comme cela a été mentionné plus tôt dans la réponse qui avait la solution de liaison de largeur, il n'a pas redimensionné l'élément lorsque le parent a été redimensionné en raison de l'agrandissement de la fenêtre ou plus petite.
David Rector
8

Les deux réponses données ont fonctionné pour le problème que j'ai déclaré - Merci!

Dans ma vraie application cependant, j'essayais de contraindre un panneau à l'intérieur d'un ScrollViewer et la méthode de Kent ne gérait pas très bien cela pour une raison que je n'ai pas pris la peine de localiser. Fondamentalement, les contrôles pourraient s'étendre au-delà du paramètre MaxWidth et vaincre mon intention.

La technique de Nir fonctionnait bien et n'avait pas de problème avec le ScrollViewer, bien qu'il y ait une chose mineure à surveiller. Vous voulez être sûr que les marges droite et gauche de la zone de texte sont définies sur 0, sinon elles vous gêneront. J'ai également modifié la liaison pour utiliser ViewportWidth au lieu de ActualWidth pour éviter les problèmes lorsque la barre de défilement verticale est apparue.

Scott Bussinger
la source
6

Vous pouvez l'utiliser pour la largeur de votre DataTemplate:

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

Assurez-vous que votre racine DataTemplate a Margin = "0" (vous pouvez utiliser un panneau comme racine et définir la marge sur les enfants de cette racine)

Filip Skakun
la source
1

Fonctionnellement similaire à la réponse acceptée, mais ne nécessite pas que l'élément parent soit spécifié:

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

Peut-être que je peux encore aider quelqu'un qui se heurte à cette question, car c'est un problème très ancien.

J'avais aussi besoin de ça et j'ai écrit un comportement pour m'en occuper. Voici donc le comportement:

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

Ensuite, vous pouvez l'utiliser comme ceci:

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

Et enfin oublier d'utiliser l' System.Windows.Interactivityespace de noms pour utiliser le comportement.

YC
la source
0

j'utiliserais 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
la source
0

Dans mon cas, j'ai dû mettre une zone de texte dans un panneau de pile afin d'étirer la zone de texte sur le côté gauche. Merci au post précédent. Juste pour un exemple, j'ai défini une couleur d'arrière-plan pour voir ce qui se passe lorsque la taille de la fenêtre change.

<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>
sparedev
la source