HorizontalAlignment = Stretch, MaxWidth und Left gleichzeitig ausgerichtet?

95

Das scheint einfach zu sein, aber ich bin ratlos. In WPF möchte ich eine TextBox, die sich auf die Breite des übergeordneten Elements erstreckt, jedoch nur auf eine maximale Breite. Das Problem ist, dass ich möchte, dass es innerhalb seines Elternteils gerechtfertigt bleibt. Um es zu dehnen, müssen Sie HorizontalAlignment = "Stretch" verwenden, aber dann wird das Ergebnis zentriert. Ich habe mit HorizontalContentAlignment experimentiert, aber es scheint nichts zu bewirken.

Wie kann ich erreichen, dass dieses blaue Textfeld mit der Größe des Fensters wächst, eine maximale Breite von 200 Pixel hat und gerechtfertigt bleibt?

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

Was ist der Trick?

Scott Bussinger
quelle

Antworten:

89

Sie können festlegen , HorizontalAlignmentnach links, stellen Sie MaxWidthund dann binden Widthan die ActualWidthdes übergeordneten Elements:

<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
quelle
7
Wird nicht automatisch angepasst. Scheint inhaltsfähig zu sein. Vermisse ich etwas?
Gishu
Dies scheint meinen Silverlight-Player zum Absturz zu bringen
Resopollution
2
@Gishu, stellen Sie sicher, dass Sie HorizontalAlignment="Stretch"auf das Container Element setzen. (ps, mir ist klar, dass Sie diese Frage vor über 6 Jahren gestellt haben.)
David Murdoch
50
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" MaxWidth="200"/>
    </Grid.ColumnDefinitions>

    <TextBox Background="Azure" Text="Hello" />
</Grid>
Kent Boogaart
quelle
Ich denke, Sie müssen VerticalAlignment = "Top" für das Textfeld setzen. Scheint standardmäßig gestreckt zu sein.
Gishu
1
+1. Schön und sauber. Jedes Mal, wenn ich versuche, das Layout durch Binden an eine tatsächliche Breite zu verwalten (wie in der akzeptierten Antwort), werden die Dinge chaotisch.
Eren Ersönmez
1
Ich bin gerade auf diese Frage gestoßen, als ich versucht habe, das gleiche Problem zu lösen. In meinem Fall ist dies die beste Antwort, da es in WinRT funktioniert. Die andere Antwort lautet nicht, da Sie ActualWidth in WinRT nicht binden können.
Slade
Slade - Ich habe dies gerade in einer Windows Store-App getan: MaxWidth = "{Binding ActualWidth, ElementName = Layout}" und es hat gut funktioniert, um MaxWidth an eine andere ActualWidth-Eigenschaft zu binden. Ich bin mir nicht sicher, warum dies bei mir funktioniert hat, aber es hat das getan, was ich erwartet hatte, und wie bereits in der Antwort mit der Breitenbindungslösung erwähnt, wurde die Größe des Elements nicht geändert, wenn die Größe des übergeordneten Elements geändert wurde, weil das Fenster größer oder größer wurde kleiner.
David Rector
8

Beide Antworten funktionierten für das von mir angegebene Problem - Danke!

In meiner realen Anwendung habe ich jedoch versucht, ein Panel in einem ScrollViewer einzuschränken, und Kents Methode hat das aus irgendeinem Grund nicht sehr gut gehandhabt. Ich habe mich nicht darum gekümmert, es aufzuspüren. Grundsätzlich könnten die Steuerelemente über die MaxWidth-Einstellung hinaus erweitert werden und meine Absicht zunichte machen.

Nirs Technik funktionierte gut und hatte kein Problem mit dem ScrollViewer, obwohl es eine Kleinigkeit gibt, auf die man achten muss. Sie möchten sicherstellen, dass der rechte und der linke Rand der TextBox auf 0 gesetzt sind, da sie sonst im Weg stehen. Ich habe auch die Bindung geändert, um ViewportWidth anstelle von ActualWidth zu verwenden, um Probleme zu vermeiden, wenn die vertikale Bildlaufleiste angezeigt wird.

Scott Bussinger
quelle
6

Sie können dies für die Breite Ihrer DataTemplate verwenden:

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

Stellen Sie sicher, dass Ihr DataTemplate-Stamm Margin = "0" hat (Sie können ein Bedienfeld als Stamm verwenden und den Rand auf die untergeordneten Elemente dieses Stamms setzen).

Filip Skakun
quelle
1

Funktionell ähnlich der akzeptierten Antwort, erfordert jedoch nicht die Angabe des übergeordneten Elements:

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

Vielleicht kann ich noch jemandem helfen, der auf diese Frage stößt, weil dies ein sehr altes Problem ist.

Ich brauchte das auch und schrieb ein Verhalten, um mich darum zu kümmern. Also hier ist das Verhalten:

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

Dann können Sie es so verwenden:

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

Und schließlich zu vergessen, den System.Windows.InteractivityNamespace zu verwenden, um das Verhalten zu verwenden.

YC
quelle
0

ich würde ... benutzen 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
quelle
0

In meinem Fall musste ich ein Textfeld in ein Stapelfenster einfügen, um das Textfeld auf der linken Seite zu dehnen. Danke an vorherigen Beitrag. Nur als Beispiel habe ich eine Hintergrundfarbe festgelegt, um zu sehen, was passiert, wenn sich die Fenstergröße ändert.

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