HorizontalAlignment = Stretch, MaxWidth และ Left aligned ในเวลาเดียวกัน?


96

ดูเหมือนว่ามันจะง่าย แต่ฉันก็นิ่งงัน ใน WPF ฉันต้องการกล่องข้อความที่ขยายไปตามความกว้างของพาเรนต์ แต่ต้องมีความกว้างสูงสุดเท่านั้น ปัญหาคือฉันต้องการให้มันถูกปล่อยให้เป็นธรรมภายในพาเรนต์ หากต้องการยืดคุณต้องใช้ HorizontalAlignment = "Stretch" แต่ผลลัพธ์จะอยู่กึ่งกลาง ฉันได้ทดลองกับ HorizontalContentAlignment แล้ว แต่ดูเหมือนจะไม่ทำอะไรเลย

ฉันจะทำให้กล่องข้อความสีฟ้าโตขึ้นตามขนาดของหน้าต่างมีความกว้างสูงสุด 200 พิกเซลได้อย่างไรและถูกปล่อยให้เป็นธรรม?

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

เคล็ดลับคืออะไร?

คำตอบ:


89

คุณสามารถตั้งค่าHorizontalAlignmentเป็นซ้ายตั้งค่าของคุณMaxWidthแล้วเชื่อมโยงWidthกับActualWidthองค์ประกอบหลัก:

<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
ไม่ได้ปรับอัตโนมัติ .. ดูเหมือนจะพอดีกับเนื้อหา .. ฉันขาดอะไรไปหรือเปล่า?
Gishu

ดูเหมือนว่าจะทำให้เครื่องเล่น Silverlight ของฉันพัง
resopollution

2
@Gishu ให้แน่ใจว่าคุณตั้งค่าHorizontalAlignment="Stretch"ในContainer องค์ประกอบ (PS ฉันรู้ว่าคุณถามคำถามนั้นเมื่อ 6 ปีก่อน)
David Murdoch

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

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

ฉันคิดว่าคุณต้องตั้ง VerticalAlignment = "Top" สำหรับกล่องข้อความ .. ดูเหมือนจะยืดออกไปโดยปริยาย
Gishu

1
+1. สวยและสะอาด ทุกครั้งที่ฉันพยายามจัดการเลย์เอาต์โดยผูกกับความกว้างจริง (เช่นเดียวกับในคำตอบที่ยอมรับ) สิ่งต่างๆก็ยุ่งเหยิง
Eren Ersönmez

1
ฉันเพิ่งเจอคำถามนี้ในขณะที่พยายามแก้ปัญหาเดียวกัน ในกรณีของฉันนี่เป็นคำตอบที่ดีที่สุดเนื่องจากทำงานใน WinRT คำตอบอื่นไม่ได้เป็นเพราะคุณไม่สามารถผูกกับ ActualWidth ใน WinRT ได้
Slade

Slade - ฉันเพิ่งทำสิ่งนี้ในแอป Windows Store: MaxWidth = "{Binding ActualWidth, ElementName = Layout}" และทำงานได้ดีในการผูก MaxWidth กับองค์ประกอบอื่น ๆ คุณสมบัติ ActualWidth ฉันไม่แน่ใจว่าทำไมสิ่งนี้ถึงได้ผลสำหรับฉัน แต่มันทำในสิ่งที่ฉันคาดไว้และเช่นเดียวกับที่กล่าวไว้ก่อนหน้านี้ในคำตอบที่มีโซลูชันการผูกความกว้างมันไม่ได้ปรับขนาดองค์ประกอบเมื่อผู้ปกครองปรับขนาดเนื่องจากทำให้หน้าต่างใหญ่ขึ้นหรือ เล็กกว่า
David Rector

8

คำตอบทั้งสองได้ผลสำหรับปัญหาที่ฉันระบุ - ขอบคุณ!

ในแอปพลิเคชันจริงของฉันฉันพยายาม จำกัด พาเนลภายใน ScrollViewer และวิธีการของ Kent ก็ไม่ได้จัดการกับสิ่งนั้นได้ดีนักด้วยเหตุผลบางอย่างฉันไม่ต้องกังวลที่จะติดตาม โดยทั่วไปการควบคุมสามารถขยายเกินการตั้งค่า MaxWidth และเอาชนะความตั้งใจของฉัน

เทคนิคของ Nir ทำงานได้ดีและไม่มีปัญหากับ ScrollViewer แม้ว่าจะมีสิ่งเล็กน้อยที่ต้องระวัง คุณต้องการให้แน่ใจว่าระยะขอบขวาและซ้ายบนกล่องข้อความถูกตั้งค่าเป็น 0 มิฉะนั้นจะเข้ามาขวางทาง ฉันยังเปลี่ยนการผูกเพื่อใช้ ViewportWidth แทน ActualWidth เพื่อหลีกเลี่ยงปัญหาเมื่อแถบเลื่อนแนวตั้งปรากฏขึ้น


6

คุณสามารถใช้สิ่งนี้สำหรับความกว้างของ DataTemplate ของคุณ:

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

ตรวจสอบให้แน่ใจว่ารูท DataTemplate ของคุณมี Margin = "0" (คุณสามารถใช้บางพาเนลเป็นรูทและตั้งค่า Margin เป็นชายด์ของรูทนั้น)


1

ทำงานคล้ายกับคำตอบที่ยอมรับ แต่ไม่จำเป็นต้องระบุองค์ประกอบหลัก:

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

1

บางทีฉันยังสามารถช่วยใครสักคนที่มีปัญหากับคำถามนี้ได้เพราะนี่เป็นปัญหาเก่ามาก

ฉันต้องการสิ่งนี้เช่นกันและเขียนพฤติกรรมเพื่อดูแลสิ่งนี้ นี่คือพฤติกรรม:

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

จากนั้นคุณสามารถใช้งานได้ดังนี้:

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

และสุดท้ายจะลืมใช้System.Windows.Interactivityเนมสเปซเพื่อใช้พฤติกรรม


0

ฉันจะใช้ 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

ในกรณีของฉันฉันต้องใส่กล่องข้อความลงในแผงสแต็กเพื่อยืดกล่องข้อความทางด้านซ้าย ขอบคุณโพสต์ก่อนหน้า ตัวอย่างเช่นฉันตั้งค่าสีพื้นหลังเพื่อดูว่าเกิดอะไรขึ้นเมื่อขนาดหน้าต่างเปลี่ยนไป

<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>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.