阻止 ScrollViewer 中的 TextBox 随着内容增长

Stop TextBox in ScrollViewer from growing with content

我有一个 Horizo​​ntalScrollBarVisibility 设置为 "Auto" 的 ScrollViewer,其中包含一个 TextBox。问题在于,当用户输入文本时,TextBox 会不断增长以显示全部内容。我需要更改什么,以便 TextBox 仅获取可用宽度(但不小于给定的最小宽度)?

仅当可用水平滚动条 space 不足以满足给定的最小宽度时,才应显示水平滚动条。

只有当有更多水平 space 可用时,TextBox 才应该增长。

<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="50"/>
            <ColumnDefinition Width="*" MinWidth="50"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <TextBlock Grid.Column="0" Text="test:"/>
        <TextBox Grid.Column="1"/>
    </Grid>
</ScrollViewer>

即使满足 MinWidth 约束,水平滚动条也会出现:

这似乎是一个普遍的问题,但我还没有在网上找到满意的解决方案。

这是我的解决方案:

<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="50"/>
            <ColumnDefinition Width="*" MinWidth="100"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <TextBlock Grid.Column="0" Text="test:"/>

        <local:TextBoxDecorator Grid.Column="1">
            <TextBox Text="content content content content content content"/>
        </local:TextBoxDecorator>
    </Grid>
</ScrollViewer>

c#

public class TextBoxDecorator : Decorator {
    // properties
    public override UIElement Child {
        get {
            return base.Child;
        }
        set {
            var oldValue = base.Child;

            if (oldValue != null) {
                var binding = BindingOperations.GetBinding(oldValue, FrameworkElement.WidthProperty);
                if ((binding != null) && (binding.Source == this))
                    BindingOperations.ClearBinding(oldValue, FrameworkElement.WidthProperty);
            }

            base.Child = value;

            if ((value != null) &&
                BindingOperations.GetBinding(value, FrameworkElement.WidthProperty) == null)
                BindingOperations.SetBinding(
                    value,
                    FrameworkElement.WidthProperty,
                    new Binding() {
                        Source = this,
                        Path = new PropertyPath(FrameworkElement.ActualWidthProperty),
                        Mode = BindingMode.OneWay
                    });
        }
    }

    // methods
    protected override Size MeasureOverride(Size constraint) {
        Size result = base.MeasureOverride(constraint);

        if (double.IsInfinity(constraint.Width))
            result.Width = (Child as FrameworkElement)?.MinWidth ?? 0.0;

        return result;
    }
}

如果这对您有帮助或您有任何反馈,请告诉我。