HorizontalAlignment = Regangkan, MaxWidth, dan Rata kiri secara bersamaan?

95

Sepertinya ini mudah tapi saya bingung. Di WPF, saya ingin TextBox yang membentang ke lebar induknya, tetapi hanya untuk lebar maksimum. Masalahnya adalah saya ingin itu dibenarkan di dalam induknya. Untuk membuatnya meregang Anda harus menggunakan HorizontalAlignment = "Stretch", tapi kemudian hasilnya dipusatkan. Saya telah bereksperimen dengan HorizontalContentAlignment, tetapi tampaknya tidak melakukan apa pun.

Bagaimana caranya agar kotak teks biru ini tumbuh dengan ukuran jendela, memiliki lebar maksimum 200 piksel, dan dibiarkan rata?

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

Apa triknya?

Scott Bussinger
sumber

Jawaban:

89

Anda dapat mengatur HorizontalAlignmentke Kiri, mengatur Anda MaxWidthdan kemudian mengikat Widthke ActualWidthelemen induk:

<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
sumber
7
Tidak otomatis ukurannya .. Tampaknya sesuai dengan konten .. apakah saya melewatkan sesuatu?
Gishu
Hal ini tampaknya merusak pemutar silverlight saya
polusi ulang
2
@Gishu, pastikan Anda mengatur HorizontalAlignment="Stretch"pada Container elemen. (ps, saya sadar Anda mengajukan pertanyaan itu lebih dari 6 tahun yang lalu.)
David Murdoch
51
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" MaxWidth="200"/>
    </Grid.ColumnDefinitions>

    <TextBox Background="Azure" Text="Hello" />
</Grid>
Kent Boogaart
sumber
Saya pikir Anda perlu mengatur VerticalAlignment = "Top" untuk kotak teks .. tampaknya akan meregang secara default.
Gishu
1
+1. Bagus dan bersih. Setiap kali saya mencoba mengelola tata letak dengan mengikat beberapa lebar sebenarnya (seperti dalam jawaban yang diterima), semuanya menjadi berantakan.
Eren Ersönmez
1
Saya baru saja menemukan pertanyaan ini ketika mencoba memecahkan masalah yang sama. Dalam kasus saya, ini adalah jawaban terbaik karena berfungsi di WinRT. Jawaban lain tidak karena Anda tidak dapat mengikat ActualWidth di WinRT.
Slade
Slade - Saya baru saja melakukan ini di aplikasi Windows Store: MaxWidth = "{Binding ActualWidth, ElementName = Layout}" dan berfungsi dengan baik untuk mengikat MaxWidth ke elemen lain properti ActualWidth. Saya tidak yakin mengapa ini berhasil untuk saya tetapi itu melakukan apa yang saya harapkan, dan seperti yang disebutkan sebelumnya dalam jawaban yang memiliki solusi pengikatan Lebar, itu tidak mengubah ukuran elemen ketika induk diubah ukurannya karena membuat jendela lebih besar atau lebih kecil.
David Rector
8

Kedua jawaban yang diberikan berhasil untuk masalah yang saya nyatakan - Terima kasih!

Namun dalam aplikasi saya yang sebenarnya, saya mencoba membatasi panel di dalam ScrollViewer dan metode Kent tidak menanganinya dengan baik karena alasan tertentu saya tidak repot-repot melacaknya. Pada dasarnya kontrolnya bisa berkembang melampaui pengaturan MaxWidth dan mengalahkan niat saya.

Teknik Nir bekerja dengan baik dan tidak memiliki masalah dengan ScrollViewer, meskipun ada satu hal kecil yang harus diperhatikan. Anda ingin memastikan margin kanan dan kiri pada TextBox disetel ke 0 atau mereka akan menghalangi. Saya juga mengubah pengikatan untuk menggunakan ViewportWidth daripada ActualWidth untuk menghindari masalah saat scrollbar vertikal muncul.

Scott Bussinger
sumber
6

Anda dapat menggunakan ini untuk Lebar DataTemplate Anda:

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

Pastikan root DataTemplate Anda memiliki Margin = "0" (Anda dapat menggunakan beberapa panel sebagai root dan menyetel Margin ke turunan root tersebut)

Filip Skakun
sumber
1

Secara fungsional mirip dengan jawaban yang diterima, tetapi tidak memerlukan elemen induk untuk ditentukan:

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

Mungkin saya masih dapat membantu seseorang yang mengalami pertanyaan ini, karena ini adalah masalah yang sangat lama.

Saya membutuhkan ini juga dan menulis sebuah perilaku untuk mengatasinya. Jadi inilah perilakunya:

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

Kemudian Anda bisa menggunakannya seperti ini:

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

Dan akhirnya lupa menggunakan System.Windows.Interactivitynamespace untuk menggunakan perilaku tersebut.

YC
sumber
0

Saya akan menggunakan 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
sumber
0

Dalam kasus saya, saya harus meletakkan kotak teks ke dalam panel tumpukan untuk meregangkan kotak teks di sisi kiri. Terima kasih untuk posting sebelumnya. Sebagai contoh, saya mengatur warna latar belakang untuk melihat apa yang terjadi ketika ukuran jendela berubah.

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