HorizontalAlignment=Stretch, MaxWidth и Left выровнены одновременно?
Кажется, это должно быть легко, но я в тупике. В 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>
В чем подвох?
9 ответов
Вы можете установить 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>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" MaxWidth="200"/>
</Grid.ColumnDefinitions>
<TextBox Background="Azure" Text="Hello" />
</Grid>
Оба ответа помогли решить поставленную мною проблему. Спасибо!
Однако в моем реальном приложении я пытался ограничить панель внутри ScrollViewer, и метод Кента не справился с этим очень хорошо, по какой-то причине я не удосужился его отследить. По сути, элементы управления могут выходить за пределы настроек MaxWidth и победить мои намерения.
Техника Нира работала хорошо и не имела проблем с ScrollViewer, хотя есть одна небольшая вещь, на которую следует обратить внимание. Вы хотите убедиться, что правое и левое поля в TextBox установлены в 0, иначе они будут мешать. Я также изменил привязку, чтобы использовать ViewportWidth вместо ActualWidth, чтобы избежать проблем при появлении вертикальной полосы прокрутки.
Вы можете использовать это для ширины вашего DataTemplate:
Width="{Binding ActualWidth,RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ScrollContentPresenter}}}"
Убедитесь, что ваш корень DataTemplate имеет Margin="0" (вы можете использовать некоторую панель в качестве корня и установить Margin для дочерних элементов этого корня)
Может быть, я все еще могу помочь кому-то, кто сталкивается с этим вопросом, потому что это очень старая проблема.
Я также нуждался в этом и написал поведение, чтобы позаботиться об этом. Итак, вот поведение:
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
Пространство имен, чтобы использовать поведение.
Функционально аналогичен принятому ответу, но не требует указания родительского элемента:
<TextBox
Width="{Binding ActualWidth, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type FrameworkElement}}}"
MaxWidth="500"
HorizontalAlignment="Left" />
Эти ответы не сработали для меня, потому что мне нужно былоTextBox
растягиваться (т.е. потреблять все доступное пространство), пока не достигнет своегоMaxWidth
и, если доступно больше места, выровняйте по правому краю.
Я создал этот простой элемент управления, который работает в соответствии с ответом Y C, но не требуетSystem.Windows.Interactivity
:
public class StretchAlignmentPanel : ContentControl
{
public StretchAlignmentPanel()
{
this.SizeChanged += StretchAlignmentPanel_SizeChanged;
}
public static readonly DependencyProperty HorizontalFallbackAlignmentProperty = DependencyProperty.Register(
nameof(HorizontalFallbackAlignment), typeof(HorizontalAlignment), typeof(StretchAlignmentPanel), new PropertyMetadata(HorizontalAlignment.Stretch));
public HorizontalAlignment HorizontalFallbackAlignment
{
get { return (HorizontalAlignment)GetValue(HorizontalFallbackAlignmentProperty); }
set { SetValue(HorizontalFallbackAlignmentProperty, value); }
}
public static readonly DependencyProperty VerticalFallbackAlignmentProperty = DependencyProperty.Register(
nameof(VerticalFallbackAlignment), typeof(VerticalAlignment), typeof(StretchAlignmentPanel), new PropertyMetadata(VerticalAlignment.Stretch));
public VerticalAlignment VerticalFallbackAlignment
{
get { return (VerticalAlignment)GetValue(VerticalFallbackAlignmentProperty); }
set { SetValue(VerticalFallbackAlignmentProperty, value); }
}
private void StretchAlignmentPanel_SizeChanged(object sender, System.Windows.SizeChangedEventArgs e)
{
var fe = this.Content as FrameworkElement;
if (fe == null) return;
if(e.WidthChanged) applyHorizontalAlignment(fe);
if(e.HeightChanged) applyVerticalAlignment(fe);
}
private void applyHorizontalAlignment(FrameworkElement fe)
{
if (HorizontalFallbackAlignment == HorizontalAlignment.Stretch) return;
if (this.ActualWidth > fe.MaxWidth)
{
fe.HorizontalAlignment = HorizontalFallbackAlignment;
fe.Width = fe.MaxWidth;
}
else
{
fe.HorizontalAlignment = HorizontalAlignment.Stretch;
fe.Width = double.NaN;
}
}
private void applyVerticalAlignment(FrameworkElement fe)
{
if (VerticalFallbackAlignment == VerticalAlignment.Stretch) return;
if (this.ActualHeight > fe.MaxHeight)
{
fe.VerticalAlignment = VerticalFallbackAlignment;
fe.Height= fe.MaxHeight;
}
else
{
fe.VerticalAlignment = VerticalAlignment.Stretch;
fe.Height= double.NaN;
}
}
}
Его можно использовать следующим образом:
<controls:StretchAlignmentPanel HorizontalFallbackAlignment="Right">
<TextBox MaxWidth="200" MinWidth="100" Text="Example"/>
</controls:StretchAlignmentPanel>
В моем случае мне пришлось поместить текстовое поле в панель стека, чтобы растянуть текстовое поле с левой стороны. Спасибо за предыдущий пост. Просто для примера я установил цвет фона, чтобы увидеть, что происходит при изменении размера окна.
<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>
Я хотел бы использовать SharedGroupSize
<Grid>
<Grid.ColumnDefinition>
<ColumnDefinition SharedGroupSize="col1"></ColumnDefinition>
<ColumnDefinition SharedGroupSize="col2"></ColumnDefinition>
</Grid.ColumnDefinition>
<TextBox Background="Azure" Text="Hello" Grid.Column="1" MaxWidth="200" />
</Grid>