web-dev-qa-db-fra.com

HorizontalAlignment = Stretch, MaxWidth et aligné à gauche en même temps?

Cela semble être facile mais je suis perplexe. Dans WPF, je voudrais une zone de texte s'étendant sur la largeur de son parent, mais uniquement sur une largeur maximale. Le problème est que je veux qu'il soit laissé justifié au sein de son parent. Pour qu'il s'étire, vous devez utiliser HorizontalAlignment = "Stretch", mais le résultat est ensuite centré. J'ai expérimenté HorizontalContentAlignment, mais cela ne semble rien faire.

Comment faire en sorte que cette zone de texte bleue grossisse avec la taille de la fenêtre, ait une largeur maximale de 200 pixels et 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?

87
Scott Bussinger

Vous pouvez définir HorizontalAlignment sur Gauche, définir votre MaxWidth et lier Width à la ActualWidth de l'é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>
84
Nir
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" MaxWidth="200"/>
    </Grid.ColumnDefinitions>

    <TextBox Background="Azure" Text="Hello" />
</Grid>
44
Kent Boogaart

Les deux réponses données ont fonctionné pour le problème que j'ai énoncé - 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 cela très bien pour une raison que je n'avais pas pris la peine de localiser. Fondamentalement, les contrôles pourraient s’étendre au-delà du paramètre MaxWidth et contrecarrer mon intention.

La technique de Nir a bien fonctionné et n'a pas eu le problème avec le ScrollViewer, bien qu'il y ait une chose mineure à surveiller. Vous voulez vous assurer 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 afin qu'elle utilise ViewportWidth au lieu de ActualWidth pour éviter les problèmes liés à l'apparition de la barre de défilement verticale.

8
Scott Bussinger

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

6
Filip Skakun

Je voudrais utiliser 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
Patrick Cairns

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

J'avais aussi besoin de ça et j'ai écrit un comportement pour m'en occuper. Alors voici 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'espace de noms System.Windows.Interactivity pour utiliser le comportement.

0
Y C