Горизонтальное выравнивание = выравнивание, максимальная ширина и левое выравнивание одновременно?

Кажется, это должно быть легко, но я в тупике. В WPF я бы хотел, чтобы TextBox растягивался до его ширины, но только до максимальной ширины. Проблема в том, что я хочу, чтобы она оставалась оправданной внутри ее родителя. Чтобы растянуть его, вы должны использовать 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>

Какой трюк?

Ответ 1

Вы можете установить 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>

Ответ 2

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

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

Ответ 3

Оба ответа, приведенные в работе для проблемы, я заявил - Спасибо!

В моем реальном приложении, однако, я пытался сдерживать панель внутри ScrollViewer, и метод Kent не справлялся с этим очень хорошо по какой-то причине, я не потрудился отслеживать. В основном, элементы управления могут расширяться за пределы настройки MaxWidth и побеждать мое намерение.

Техника Нира работала хорошо и не имела проблемы с ScrollViewer, хотя есть одна второстепенная вещь, которой нужно следить. Вы хотите быть уверены, что поля справа и слева в TextBox установлены в 0 или они будут мешать. Я также изменил привязку, чтобы использовать ViewportWidth вместо ActualWidth, чтобы избежать проблем, когда появилась вертикальная полоса прокрутки.

Ответ 4

Вы можете использовать это для ширины вашего DataTemplate:

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

Убедитесь, что ваш корень DataTemplate имеет значение Margin = "0" (вы можете использовать некоторую панель в качестве корня и установить значение Margin для дочерних элементов этого корня)

Ответ 5

Я бы использовал 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>

Ответ 6

Может быть, я все еще могу помочь кому-то, кто сталкивается с этим вопросом, потому что это очень старая проблема.

Я также нуждался в этом и написал поведение, чтобы позаботиться об этом. Итак, вот поведение:

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 имен System.Windows.Interactivity для использования поведения.